2012-05-08 93 views
0

我不明白为什么数组在两个实例之间共享,而原始类型不是。有人可以解释吗?参考和原始原型值

MyObject = function() {}; 
MyObject.prototype = {anArray : [],aString : ''}; 
var c1 = new MyObject(); 
c1.aString = 'a'; 
c1.anArray.push('a'); 
var c2 = new MyObject(); 
console.log(c2.aString); 
console.log(c2.anArray); 
+0

原始类型* *在两个实例之间共享,但您已覆盖'c1'对象的自己的值。 – zzzzBov

回答

0

当分配

c1.aString = 'a' 

分配给原型的aString领域。一个名为aString的新字段直接在c1对象中创建,并隐藏原型中的aString字段。

同时,当你调用

c1.anArray.push('a'); 

存在c1没有anArray领域,所以你引用的原型anArray。您可以通过执行

c1.anArray = new Array(); 

测试这一点,并指出,一个新的属性anArrayc1被创建,不与原型anArray干扰。在这种情况下,

console.log(c1.anArray); 
console.log(c2.anArray); 

会有不同的结果,因为c2仍然会参考anArray原型。

如果在对象和原型中(甚至在原型链中)直接存在具有相同名称的字段,并且您请求此字段的值,则解释器首先直接查看对象,只有原型链,直到它找到某个地方的领域。

但是,如果为字段赋值,它总是直接在对象中完成,而不会在其原型中完成。

2

字符串是不可变的,数组是可变的。您正在替换字符串,但修改阵列。

如果你在上覆盖而不是修改它,你会得到与数组和字符串相同的行为。

MyObject = function() {}; 
MyObject.prototype = {anArray : [],aString : ''}; 

var c1 = new MyObject(); 
c1.aString = 'a'; 
c1.anArray = [] 
c1.anArray.push('a'); 

var c2 = new MyObject(); 
console.log(c2.aString); // '' 
console.log(c2.anArray); // [] 

所以它才有意义,以把一个对象或阵列上的prototype如果你在允许所有情况下,观察变化的IT规划。否则,直接把它放在实例上。

MyObject = function() { 
    this.anArray = []; 
}; 
MyObject.prototype = {aString : ''}; 
+0

感谢您的回复。那么有什么推荐的方法来实现可变实例变量呢? –

+0

@bradmiley:将数组保持原型,并将其直接赋值给构造函数中的新对象。 –