2009-12-31 144 views
6

只是为了踢我试图在javascript中创建一个简单的数据对象。这是代码。在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; 
        }(); 
    

,然后做对我来说是以下的console.log

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

把它扔到了以下错误:

cannot access optimized closure 

它为什么会这么说?我究竟做错了什么?

感谢您的帮助。任何评论意见,将不胜感激! 干杯

+2

在'var newRover = {}'上忘记了分号和所有函数定义。 – philfreo 2009-12-31 04:43:19

+0

谢谢。会做出改变。 :) – Priyank 2009-12-31 04:50:46

+0

添加分号仍然不能解决问题,虽然 – Priyank 2009-12-31 05:04:36

回答

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; 
} 

注意还真是私有的,甚至该子类无法获取它们。没有'保护'。

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

那是什么想干什么?我无法得到你所犯的错误;以上所做的就是将该字符串的位置分配给where(在setter方法被调用之前,所以它没有定义)。

是否有更好的方法来创建这种类型的对象?

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

+0

优秀指针!它提供了大量的信息。谢谢 – Priyank 2009-12-31 06:04:51

1

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

编辑哦,我明白了,当你分配rover.where时,你实际上正在执行哪个功能。你是否想要得到一个看起来像属性的东西来实际上是一个功能?如果是这种情况,它将无法工作。如果您希望在被调用时对其进行评估,它必须是一个函数。

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

+0

,这是行不通的。我相信,如果认为如果我的闭包函数返回函数的值,而不是函数本身,那么哪里成为一个属性的权利?不是一个功能。 – Priyank 2009-12-31 05:28:25

+0

正确 - 但是当你调用'console.log(rover1.where)',你试图打印出我认为Firebug不能的函数定义(在这种情况下) – 2009-12-31 05:34:33

+0

看到编辑,我没有意识到新的'where'函数的语法:) – 2009-12-31 05:54:38

2

Q1:您可以创建在JavaScript“类”“私有”的成员。在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中的对象范围受称为闭包的奇怪概念支配。据我所知,没有任何其他流行launguage像C没有平行概念+/Java的等

虽然我理解闭包是什么,我不能把它的话。也许一个演示将帮助您:

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

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

closureDemo(); 

现在,而setDone是从内部doLater调用,它仍可以访问done在closureDemo,即使done范围(在常规程序意义上的)

我想你会明白更多,当你阅读this。Q2:我只能说我在做什么;我只能说我在做什么;我不知道这是否更好。如果我写你的代码,它应该是这样的:

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(); 

注意要点:roverObject

  1. 资本“类名”的第一个字母
  2. 使用这种替代
  3. 这个函数是一个纯粹的构造函数。它什么都不返回。

Q3:如果你想要做的继承,那么我的方法(使用本)将行不通。相反,公共方法应该是RoverObjectprototype的一部分。阅读this。优秀的材料。

希望有所帮助。


编辑:你的代码的工作方式有问题。问题:

  1. 你的功能没有按顾名思义去做。它的名字最好是createRoverObject,因为这正是它所做的。它不像类构造函数那样工作
  2. 你的类支持的方法是对象的一部分,但数据成员不是。虽然这可能起作用(事实并非如你的console.log()问题所示),但它不是一种在javascript中实现类的好方法。这里的问题是关闭。再次,我无法明确具体是什么问题,但我可以smell it
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();