2013-12-10 147 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 

有人可以解释我吗? 谢谢...

编辑:

这里有一个解决方案:

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

你是变异的共享对象(不同诱变是当你重新分配子属性或调用改变对象的功能)。道具是共享的,因为它在原型上,并且你不重新赋值它(prop = newValue),如果你重新赋值它,那么道具会被实例(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.objb.obj引用相同obj两者a.obj.valueb.obj.value2在这个例子中

1

思考作为属性在所有实例之间共享的原型属性。
然而你可以在每个实例上覆盖它,这就是你在第一个例子中所做的。
一旦在每个实例中重写,您不再使用obj.prop访问原型属性,该属性现在引用实例属性。您需要使用obj.prototype.prop再次阅读它,但是这种语法是非法的:您可以使用obj.__proto__.prop(非标准)或Object.getPrototypeOf(obj).prop(EcmaScript 5)来执行此操作。
在第二个实例中,您不要更改构造函数中的属性:而是更改此属性的属性。所以两个构造函数都访问同一个对象,然后改变它的一个属性值,所以最后设置它将会'取胜'。这里原型属性并未被实例属性覆盖('隐藏'),而是实际访问obj.prototype.prop访问obj.prop。

1

发生这种情况是因为在JS中,对象是通过引用传递的,而原语不是。

由于原型在2个实例之间共享,因此修改其上的对象将更新所有实例。

+1

在JS对象传递BY VALUE这是一个参考 - 有一个细微差别 – Adassko