Почему свойства экземпляра, в котором хранятся примитивные значения, а не ссылки, обновляются при обновлении прототипа, если свойство не было установлено самим экземпляром?
Приведу пример:
var Obj = function () {};
Obj.prototype.num = 1;
var myObj = new Obj();
var myOtherObj = new Obj();
console.log(myObj.num); //logs 1
console.log(myOtherObj.num); //logs 1
//After instances are created they still share the value (which is strange):
Obj.prototype.num = 3;
console.log(myObj.num); //logs 3
console.log(myOtherObj.num); //logs 3
//Update one of the instances property
myObj.num += 2;
console.log(myObj.num); //logs 5
console.log(myOtherObj.num); //logs 3
//Here it gets weird:
Obj.prototype.num = 4;
console.log(myObj.num); //logs 5 not updated
console.log(myOtherObj.num); //logs 4 updated
Здесь есть пара странностей:
После создания экземпляра обновление определения класса обновляет значение экземпляра тогда и только тогда, когда оно никогда не обновлялось самим экземпляром.
Если я попытаюсь объяснить это, мне покажется, что изначально у экземпляра нет собственного свойства num
, и поиск происходит там, где оно обнаружено в прототипе, но как только вы действительно установите свойство (внутренне с помощью this.num
или внешне с помощью instanceName.num
), вы создать свойство экземпляра.
Это не похоже на то, что говорится в спецификации ECMA5:
Значение свойства прототипа используется для инициализации внутреннего свойства [[Prototype]] вновь созданного объекта перед вызовом объекта Function в качестве конструктора для этого вновь созданного объекта.
Похоже, он должен заполнить экземпляры внутреннего [[Prototype]], но все же его можно изменить, обновив свойство прототипа конструктора. Я понимаю, что если я установлю свойство определения класса для объекта, такого как массив, ссылка фактически передается экземпляру, и обновление массива в любом месте изменит свойство для всех, но это примитивные значения, и, похоже, имеет много смысла.