看看这段代码:
var Test = {
options: {
name: 'foo'
},
name: 'foo',
init: function (name) {
this.name = name;
this.options.name = name;
}
};
var dict = {};
for (var i = 0; i < 3; i++) {
var obj = Object.create(Test);
obj.init(i);
dict[i] = obj;
}
我不明白为什么对象dict中的dict [X] .options.name中的所有属性 具有相同值(2)的值,并且dict [X] .name中的属性具有不同的值 ?
答案 0 :(得分:1)
看起来与通过引用传递值有关。
对象Test
包含对属性options
中另一个对象的引用。当创建Test
的新实例时,新实例将获得对现有options
实例的引用,而不是获取该对象的新副本。
粗略的图像会是这样的
您可以通过在代码底部添加以下语句来检查它
alert(Test.options== dict[0].options);
答案 1 :(得分:1)
documentation很清楚:
使用指定的原型对象和属性创建一个新对象。
因此Test
将成为新对象的原型。所有实例都引用相同的原型,而options
是一个对象,它们也共享对此的引用。
关系如下:
+------------+ +---------+ +--------+
| Instance 1 |----->| Test | | Object |
+------------+ | | | |
| options-|------>| name |
| name | +--------+
+---------+
^
+------------+ |
| Instance 2 |-----------+
+------------+
现在,由于options
是一个对象,如果你为它指定一个新属性,比如
instance1.object.name2 = 'bar';
您实际上正在访问Test.options
。结果将是:
+------------+ +---------+ +--------+
| Instance 1 |----->| Test | | Object |
+------------+ | | | |
| options-|------>| name |
| name | | name2 |
+---------+ +--------+
^
+------------+ |
| Instance 2 |-----------+
+------------+
但是当您将新值分配给name
时,将在该实例中创建新属性name
。所以当你这样做时:
instance1.name = 'bar';
结果将是
+------------+ +---------+ +--------+
| Instance 1 |----->| Test | | Object |
| | | | | |
| name | | options-+------>| name |
+------------+ | name | +--------+
+---------+
^
+------------+ |
| Instance 2 |-----------+
+------------+
如果不是仅仅访问或分配/ options
的属性,而是为其分配了新值,就会发生同样的情况:
instance1.options = {name: 'another name'};
结果:
+--------+
| Object |
| |
| name |
+--------+
^
+------------+ | +---------+ +--------+
| Instance 1 |--+-->| Test | | Object |
| | | | | | |
| options----+--+ | options-|------>| name |
+------------+ | name | +--------+
+---------+
^
+------------+ |
| Instance 2 |-----------+
+------------+
由于属性查找的工作方式,instance1.options
将返回原型链中最近(最近)options
属性的值。在我们为实例设置name
或options
后,它将返回这些值,而不是原型(Test
)的值。
答案 2 :(得分:0)
我觉得你在这里有点困惑。
options: {
name: 'foo'
},
name: 'foo'
当你定义它们,然后在你的Object.create()
语句中使用时,属于原型,因此对于具有相同原型的所有对象都是相同的。
您看到name
属性发生更改的原因是您在每个实例上创建了它(基本上覆盖了原型中定义的属性),方法是调用:
this.name = name;
对象属性不会发生的事情,因为您从未直接分配它。相反,它需要最后指定的值(在您的示例中为2)。
你写过:
this.options = {};
this.options.name = name;
在init
函数中 - options.name将在每个实例上被覆盖,就像你想要的那样。