Прототип объекта может быть изменен из экземпляра - PullRequest
2 голосов
/ 01 октября 2011

Может ли кто-нибудь разумно объяснить мне это:

function One() {}

One.prototype.obj = { key: 'value' };
One.prototype.str = 'string';

var inst1 = new One(),
    inst2 = new One();

// now let’s change some things in our second instance

inst2.obj.key = 'buh!';
inst2.str = 'buh!';

// ok, so what happens to our other instance?

console.log( inst1.str ); // Yields 'string' (unaffected, expected)
console.log( inst1.obj.key ); // Yields 'buh!' (!!)

console.log( One.prototype.obj.key ); // is also 'buh!'

Похоже, что если прототип содержит объект, экземпляр, который вы создаете с помощью ключевого слова new, имеет этот объект, но если вы его измените, вы также измените объект-прототип, влияя таким образом на все экземпляры, например наследование одного брата -pattern ...

Так ли это должно работать?

Ответы [ 2 ]

2 голосов
/ 01 октября 2011

На самом деле, Javascript не копирует ничего из прототипа.Все, что вы определяете в прототипе, существует только один раз (в самом прототипе) и используется повторно, поскольку один и тот же экземпляр прототипа передается всем объектам.

Когда вы обращаетесь к свойству объекта, объект проверяет, неэто определяется само по себе.Если это так, он вернет значение, связанное с этим свойством.Если это не так, он делегирует вызов своему прототипу, который отныне будет нести ответственность за то, что происходит.Вот почему «наследование» (повторное использование кода) в Javascript лучше называть делегированием.

В доступе для записи все немного иначе.Если вы установите свойство для объекта, оно будет «скрывать» значение локально.По этой причине свойство str не изменяется, оно фактически определено в объекте inst2.Но если вы delete inst2.str и сделаете еще один console.log( inst2.str ), вы заметите, что он вернет старое значение.

PS: Если вы хотите, чтобы предотвратить это, взгляните на этот учебник: http://kevlindev.com/tutorials/javascript/inheritance/index.htm

Я рекомендую прочитать все это, но если вы просто хотите мясо, посмотрите функцию KevLinDev.extend в разделе «Создание подкласса».

2 голосов
/ 01 октября 2011

Короче да.Javascript неявно копирует объекты для вас, поэтому, когда вы создаете литерал объекта в obj, все экземпляры класса One просто ссылаются на него посредством ссылки.Вместо этого вам нужно динамически создать объект obj в конструкторе:

function One(){
  this.obj = {key:'value'};
}

См. Также: многомерный объект javascript

...