Наследование и Object.Create в Javascript - PullRequest
0 голосов
/ 14 сентября 2011

посмотрите на этот код:

        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 [X] .options.name в объекте dict имеет значение то же значение (2), а свойства в dict [X] .name имеют другое значение

Ответы [ 3 ]

1 голос
/ 14 сентября 2011

Документация понятна:

Создает новый объект с указанным объектом-прототипом и свойствами.

Таким образом, 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).

1 голос
/ 14 сентября 2011

Это похоже на передачу значений по ссылке.

Объект Test содержит ссылку на другой объект в свойстве options.Когда создается новый экземпляр Test, новый экземпляр получает ссылку на существующий экземпляр options вместо получения новой копии объекта.

Грубое изображение будет выглядеть примерно так: enter image description here

Вы можете проверить это, добавив следующее утверждение внизу вашего кода

alert(Test.options== dict[0].options);
0 голосов
/ 14 сентября 2011

Я думаю, вы здесь немного запутались.

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

в том виде, как вы их определили, а затем использовали в своем операторе Object.create(), принадлежат прототипу и поэтому одинаковы для всех объектов с одинаковым прототипом.

Причина, по которой вы видите name атрибут, изменилась в том, что вы создали его для каждого экземпляра (по сути, переопределяя тот, что определен в прототипе), вызвав:

this.name = name;

То, что не происходит со свойством объекта, потому что вы никогда не назначали его напрямую. Вместо этого он принимает последнее назначенное значение (которое будет 2 в вашем примере).

Если бы вы написали:

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

в вашей функции init - options.name будет переопределено в каждом экземпляре и будет таким, как вы этого хотели.

...