0

看看这段代码:

        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 中的属性具有不同的值?

4

3 回答 3

1

文档很清楚:

使用指定的原型对象和属性创建一个新对象。

新对象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如果您不只是访问或分配 /to 的属性,而是为它分配了一个新值,也会发生同样的情况:

instance1.options = {name: 'another name'};

结果是:

           +--------+
           | Object |
           |        |
           | name   |
           +--------+
                ^
+------------+  |   +---------+       +--------+
| Instance 1 |--+-->| Test    |       | Object |
|            |  |   |         |       |        |
| options----+--+   | options-|------>| name   | 
+------------+      | name    |       +--------+
                    +---------+
                         ^
+------------+           |
| Instance 2 |-----------+
+------------+

由于属性查找的工作方式,将返回原型链中instance1.options最近(最近)属性的值。options一旦我们在实例中设置nameor options,它将返回那些值,而不是原型 ( Test) 的值。

于 2011-09-14T12:26:07.597 回答
1

它看起来与通过引用传递值有关。

该对象Test包含对 property 中另一个对象的引用options。当Test创建一个新实例时,新实例获取对现有options实例的引用,而不是获取对象的新副本。

粗略的图像将类似于 在此处输入图像描述

您可以通过在代码底部添加以下语句来检查它

alert(Test.options== dict[0].options);
于 2011-09-14T12:21:51.953 回答
0

我想你在这里有点困惑。

options: {
    name: 'foo'
},
name: 'foo'

当您定义它们,然后在您的Object.create()语句中使用它们时,它们属于原型,因此对于具有相同原型的所有对象都是相同的。

您看到name属性更改的原因是因为您通过调用在每个实例上创建了它(基本上覆盖了原型中定义的那个):

this.name = name;

对象属性不会发生的事情,因为您从未直接分配它。相反,它采用最后分配的值(在您的示例中为 2)。

你是否写过:

this.options = {};
this.options.name = name;

在您的init函数中 - options.name 将在每个实例上被覆盖,就像您想要的那样。

于 2011-09-14T12:33:21.340 回答