2013-12-10 4 views
1

У меня есть проблема, которую я не могу решить, потому что я не могу объяснить это поведение:объекта недвижимости в прототипе

var A = function(value) { 
    this.prop = value; 
}; 

A.prototype = { 
    prop: 0 
}; 

var a = new A(1); 
var b = new A(2); 

console.log(a.prop); 
console.log(b.prop); 

выход:

1 
2 

Но, с этим кодом (почти то же самое):

var A = function(value) { 
    this.prop.value = value; 
}; 

A.prototype = { 
    prop: { 
     value: 0 
    } 
}; 

var a = new A(1); 
var b = new A(2); 

console.log(a.prop.value); 
console.log(b.prop.value); 

у меня есть этот выход:

2 
2 

Может ли кто-нибудь объяснить мне это? Благодаря ...

EDIT:

Вот решение:

var A = function(value) { 
    this.prop = {}; 
    this.prop.value = value; 
}; 

A.prototype = { 

}; 

var a = new A(1); 
var b = new A(2); 

console.log(a.prop.value); 
console.log(b.prop.value); 
+0

Вы мутируете общий объект (Mutating, когда вы повторно назначить подсвойство или вызвать функцию, которая изменяет объект). prop является общим, потому что он находится на прототипе, и вы его не назначаете (prop = newValue), если вы его назначили, то prop будет затенен экземпляром (a и b). Подробнее о функциях прототипа и конструктора здесь: http://stackoverflow.com/a/16063711/1641941 – HMR

ответ

1

В примере 1, this.prop является примитивным типом , на который ссылается значение и, следовательно, не распространяется между экземплярами.

В примере 2, this.prop является Объектом которого ссылка инициализируются от прототипа из одного объекта, так что этот один объект является общим для всех случаев.

В последнем «примере» вы создаете новый объект с = {}, поэтому все экземпляры теперь имеют свой собственный объект.

Более подробно о примитивных типах: Primitive value vs Reference value

+0

Вернее: это не имеет значения если A.prototype.prop является примитивным или объектом. При назначении его в конструкторе this.prop значение prop будет затенено. Второй пример не назначает его, а мутирует. Так как примитив не может быть мутирован, единственный способ их изменить - это назначить и тем самым затенять его. В примере 1 значение prop также делится, как показано в следующем ответе: http://stackoverflow.com/a/16063711/1641941 – HMR

1

прототип создается только один раз, и это только простой объект, Чайлдс прилагаются для всех экземпляров функции он принадлежит ,

Так что это в основном то же самое, как если бы вы написать:

var obj = { value: 0 }; 

var a = {}, b = {}; 

a.obj = obj; 
b.obj = obj; 

obj.value = 2; 

, как вы можете видеть, как a.obj и b.obj ссылки на тот же obj и как a.obj.value и b.obj.value будет 2 в этом примере

1

Think свойства прототипа как свойство, разделяемое между всеми экземплярами.
Но вы можете переопределить его на каждом экземпляре, это то, что вы делаете в первом примере.
Как только вы переопределите в каждом случае, вы больше не получаете доступ к свойству prototype с obj.prop, который теперь относится к свойству экземпляра. Вам нужно будет использовать obj.prototype.prop, чтобы прочитать его снова, но этот синтаксис является незаконным: для этого вы можете использовать obj.__proto__.prop (нестандартный) или Object.getPrototypeOf(obj).prop (EcmaScript 5).
Во втором случае вы не изменяете свойство в конструкторе: вместо этого вы изменяете свойство этого свойства. Таким образом, оба конструктора получают доступ к одному и тому же объекту, а затем изменяют одно из его значений свойств, поэтому последний, чтобы установить его, будет «выигрывать». Здесь свойство prototype не переопределяется («скрыто») по свойству экземпляра, и доступ к obj.prop фактически является «obj.prototype.prop».

1

Это происходит потому, что в JS объекты передаются по ссылке, а примитивы - нет.

Поскольку прототип разделяется между двумя экземплярами, модификация объекта на нем будет обновлять все экземпляры.

+1

в объектах JS передается по VALUE, которая является ссылкой - есть небольшая разница – Adassko

Смежные вопросы