javascript中的对象创建

时间:2009-12-31 04:40:46

标签: javascript oop

我正试图在javascript中创建一个简单的数据对象。这是代码。

    var roverObject = function(){

        var newRover = {};
        var name;
        var xCord;
        var ycord;
        var direction;

        newRover.setName = function(newName) {
            name = newName;
        };

        newRover.getName = function() {
            return name;
        };

        newRover.setDirection = function(newDirection) {
            direction = newDirection;
        };

        newRover.getDirection = function() {
            return direction;
        };

        newRover.setXCord = function(newXCord) {
            xCord = newXCord;
        };

        newRover.getXCord = function() {
            return xCord;
        };

        newRover.setYCord = function(newYCord) {
            yCord = newYCord;
        };

        newRover.getYCord = function() {
            return yCord;
        };

        newRover.where = function(){
            return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction;
        };

        return newRover;
    };


    rover1 = new roverObject();
    rover2 = new roverObject();     

    rover1.setName("Mars Rover");
    rover1.setDirection("NORTH");
    rover1.setXCord(2);
    rover1.setYCord(2);
    console.log(rover1.where());
    console.log(rover1);

    rover2.setName("Moon Rover");
    rover2.setDirection("SOUTH");       
    rover2.setXCord(1);
    rover2.setYCord(1);     
    console.log(rover2.where());        
    console.log(rover2); 

关于这个创作我几乎没有问题。

  1. 我想创建一个对象,其中对象的属性/属性是私有的,对世界不可见。我成功了吗?我真的不能访问对象属性吗?
  2. 有没有更好的方法来创建这种对象?
  3. 如果我想继承这个对象,我应该做newObject.prototype = roverObject那会有用吗?这最有意义。
  4. 最后我有一个奇怪的问题。注意objet“where”的最后一个方法,它返回一个连接的字符串。在这里,我尝试使用以下代码。

            newRover.where = function(){
            return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction;
        }();
    
  5. 然后执行了以下console.log

    console.log(rover1.where);
    console.log(rover2.where);
    

    它给我留下了以下错误:

    cannot access optimized closure
    

    为什么会这么说?我做错了什么?

    感谢所有帮助。任何评论意见也将不胜感激! 干杯

5 个答案:

答案 0 :(得分:6)

  

我成功了吗?我真的不能访问对象属性吗?

事实上。您没有对象属性,roverObject函数中有局部变量。局部变量不能从外部访问,只能从roverObject函数内部的函数中访问它们。

您使用roverObject作为构造函数调用new roverObject是无关紧要的,因为您正在从函数返回不同的对象。在没有var rover1= roverObject()的情况下说new会做同样的事情。值得注意的是,[new] roverObject返回的对象是Object创建的对象{}; rover1 instanceof roverObjectfalse

如果您希望instanceof能够正常工作,则必须使用new进行调用,并在构造函数中使用this代替newRover

  

如果我想继承这个对象,我应该做一个newObject.prototype = roverObject会有用吗?这最有意义。

没有。您目前没有进行原型设计的补贴。您正在为roverObject的每个实例使用每种方法的单独副本。你可以用这种方式做对象,但它与原型设计不同。如果你想在你现在的安排中创建类似roverObject的子类的东西,你会说:

function AdvancedRover() {
    var rover= new roverObject();
    rover.doResearch= function() {
        return rover.where()+' and is doing advanced research';
    };
    return rover;
}

注意,因为基类构造函数中的'private'局部变量确实是私有的,所以即使是子类也无法获取它们。没有'受保护'。

  

newRover.where = function(){...}();

这是做什么的?我无法得到你做的错误;以上所做的就是将字符串赋给where的位置(在调用setter方法之前,所以它充满了未定义的内容)。

  

有没有更好的方法来创建这种对象?

也许。有关JavaScript中类/实例策略的讨论,请参阅this question

答案 1 :(得分:2)

Q1:你可以在javascript'classes'中创建'私人'成员。在javascript中,隐私不是由任何访问说明符决定的。相反,访问需要专门检测。例如:

function MyClass() {
    this.val = 100; // public;
    var privateVal = 200;

    function getVal() { return this.val; } // private method;
    this.getPrivateVal = function() { // public method, accessor to private variable
        return privateVal;
    }
}

javascript中的对象范围由名为闭包的奇怪概念控制。 AFAIK,在C + / Java等任何其他流行的语言中都没有并行概念。

虽然我理解闭包是什么,但我不能用语言表达。也许演示会对你有所帮助:

function closureDemo() {
    var done=false;
    function setDone() { done=true; }
    doLater(setDone);
}

function doLater(func) { setTimeout(func,1000); }

closureDemo();

现在,虽然从doLater中调用setDone,但它仍然可以在closureDemo中访问done,即使done在范围内不是(在传统的程序意义上)

我想您在阅读this时会了解更多。


第二季:我只能说我做了什么;我不知道它是否更好。如果我编写了代码,它将如下所示:

function RoverObject() {

    var newRover = {}; // privates
    var name;
    var xCord;
    var ycord;
    var direction;

    this.setName = function(newName) {
        name = newName;
    };

    this.getName = function() {
        return name;
    };

    this.setDirection = function(newDirection) {
        direction = newDirection;
    };

    // and so on...

    this.where = function(){
        return "Rover :: "+ name +" is at Location("+xCord+","+yCord+") pointing to "+direction;
    };
}
var rover1 = new RoverObject();

注意事项:

  1. “班级名称”的首字母大写
  2. 使用此代替roverObject
  3. 此函数是纯构造函数。它什么都不返回。

  4. 问题3:如果你想继承,那么我的方法(使用它)将不起作用。相反,公共方法应该是prototype RoverObject的一部分。阅读this。优秀的材料。

    希望有所帮助。


    编辑:您的代码工作方式存在问题。问题:

    1. 你的功能没有顾名思义。它的名字最好是createRoverObject,因为这正是它正在做的事情。它不像类构造函数那样工作
    2. 您的类支持的方法是对象的一部分,但数据成员不是。虽然这可能有效(并且它不是,正如您的console.log()问题所示),但它不是在javascript中实现类的好方法。这里的问题是关闭。同样,我无法明确说明具体问题是什么,但我可以smell it

答案 2 :(得分:1)

关于4. - 您正在尝试记录该函数,而不是调用该函数的结果。应该是console.log(rover1.where());我的猜测firebug(我认为它是firebug的console.log)不喜欢记录函数定义。

编辑哦,我明白了,当你指定rover.where时,你实际上正在执行where funcion。你是否试图将看起来像属性的东西真正变成一个函数?如果是这样的话它就行不通了。如果你想在被调用时对它进行评估,它必须是一个函数。

在你的情况下where在构造函数中执行会发生什么。那时你仍然在创建roverObject闭包,因此现在访问它的私有变量还为时过早。

答案 3 :(得分:0)

这只是解决你帖子的第1点。

这是一篇关于javascript私有成员的好文章及更多:
Private Members in JavaScript

答案 4 :(得分:0)

像这样定义你的对象会给你私人成员。

function RolloverObject() {
    var name;
    var xCord;
    var ycord;
    var direction;

    this.setName = function(newName) { name = newName; };
    this.getName = function() { return name; };

    this.setDirection = function(newDirection) { direction = newDirection; };
    this.getDirection = function() { return direction; };

    this.setXCord = function(newXCord) { xCord = newXCord; };
    this.getXCord = function() { return xCord; };

    this.setYCord = function(newYCord) { yCord = newYCord; };
    this.getYCord = function() { return yCord; };

    this.where = function() {
        return "Rover :: " + name + " is at Location(" + xCord + "," + yCord + ") pointing to " + direction; 
    };
}

var rolloverObject = new RolloverObject();