我有一个问题我无法解决,因为我无法解释这种行为:
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 :(得分: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 :(得分:1)
将原型属性视为在所有实例之间共享的属性
但是你可以在每个实例上覆盖它,这就是你在第一个例子中所做的
一旦在每个实例中重写,您就不再使用obj.prop访问prototype属性,而obj.prop现在引用了instance属性。您需要使用obj.prototype.prop再次读取它,但此语法是非法的:您可以使用obj.__proto__.prop
(非标准)或Object.getPrototypeOf(obj).prop
(EcmaScript 5)来执行此操作。
在第二个实例中,您不会更改构造函数中的属性:而是更改此属性的属性。所以两个构造函数都访问同一个对象,然后更改其中一个属性值,所以最后设置它将“赢”。这里,prototype属性不被instance属性覆盖('hidden'),并且访问obj.prop实际上访问'obj.prototype.prop'。
答案 2 :(得分:1)
这种情况正在发生,因为在JS中,对象是通过引用传递的,而原语则不是。
由于原型在两个实例之间共享,因此修改其上的对象将更新所有实例。
答案 3 :(得分:1)
在示例1中,this.prop
是基元类型,它由值引用,因此不在实例之间共享。
在示例2中,this.prop
是 Object ,其引用是从单个对象的原型初始化的,因此所有实例共享此单个对象
在上一个“示例”解决方案中,您使用= {}
创建一个新对象,因此所有实例现在都有自己的对象。
有关原始类型的更多详细信息:Primitive value vs Reference value