原型上的属性受到不同的影响
Properties on a prototype being affected differently
我在此代码段中使用了原型继承:
function SuperType() {
this.colors = ["red", "blue", "green"];
this.x = 1;
}
function SubType() {}
SubType.prototype = new SuperType();
var instance1 = new SubType();
instance1.colors.push("black");
instance1.x = 2;
//alert(instance1.colors); // "red,blue,green,black"
//alert(instance1.x); // 2
var instance2 = new SubType();
alert(instance2.colors); // "red,blue,green,black"
alert(instance2.x); // 1
我希望输出是
"red,blue,green"
1
或
"red,blue,green,black"
2
但我得到:
"red,blue,green,black"
1
为什么?
问题出在这里:
SubType.prototype = new SuperType();
因为SuperType
构造函数把.colors
数组放在对象上,又因为对象作为SubType
的.prototype
,所以.colors
数组在所有 SubType
个实例之间共享。
相反,在设置继承时不要调用构造函数,而是 do 在 SubType
构造函数中调用它。
function SubType() {
SuperType.apply(this, arguments);
}
SubType.prototype = Object.create(SuperType.prototype);
.x
没有同样问题的原因是数字不可变,因此当您尝试修改它时,会直接在对象上创建一个新的 x
重新使用而不是改变 .prototype
.
当您 运行 .push("black")
时,您正在使用一种修改对象(颜色列表)的方法;所以指向该对象的所有变量都会看到变化。
当您使用 = 2
时,您正在替换那个变量的值,因此其他变量仍然可以指向原始值。
写的时候
instance1.x = 2;
您正在向 instance1
添加一个名为 x
的新 属性。
instance1
的原型,你可以用instance1.__proto__
查找,不受影响。 instance1.__proto__.x
的值还是1。
当你参考
instance1.x
对象自身的 属性 instance1.x
优先于原型的 属性 instance1.__proto__.x
。我们说 x
on instance1
shadows x
on instance1.__proto__
.
当 JavaScript 计算 instance1.x
时,它会在向上移动原型链之前检查 instance1
自己的属性。所以,自己的值属性instance1.x
就是你看到的
但是当你写的时候
instance1.colors
对象 instance1
没有自己的 属性 称为 colors
。所以,JavaScript看它的原型。它找到 instance1.__proto__.colors
和 returns 其当前值。
你写的时候
instance1.colors.push("black");
您没有向 instance1
添加新的 属性。您只是修改了数组 instance1.__proto__.colors
。具有相同原型的所有对象都将看到相同的 colors
值,除非它们具有遮蔽 colors
.
的 属性
在下面的代码片段中,我创建了第三个对象 c
,它定义了一个名为 colors
的自己的 属性,它隐藏了原型的 属性 c.__proto__.colors
.
var c = new SubType();
c.colors = [ 'orange', 'purple' ];
自身的值 属性 c.colors
与原型的 属性 c.__proto__.colors
的数组不同。没有自己的 属性 colors
的对象将继续看到原型的 colors
.
的值
function SuperType() {
this.colors = ["red", "blue", "green"];
this.x = 1;
}
function SubType() {}
SubType.prototype = new SuperType();
var a = new SubType();
a.colors.push("black");
a.x = 2;
message('a.colors: ' + a.colors.join(', ')); // red, blue, green, black (prototype's colors)
message('a.x: ' + a.x); // 2 (own property x)
message('a.__proto__.x: ' + a.__proto__.x); // 1 (prototype's x)
var b = new SubType();
message('b.colors: ' + b.colors.join(', ')); // red, blue, green, black (prototype's colors)
message('b.x: ' + b.x); // 1 (prototype's x)
var c = new SubType();
// Make an own property, colors, that shadows the prototype's property.
c.colors = [ 'orange', 'purple' ];
message('c.colors: ' + c.colors.join(', ')); // orange, purple (own property colors)
message('b.colors: ' + b.colors.join(', ')); // red, blue, green, black (prototype's colors)
message('a.colors: ' + a.colors.join(', ')); // red, blue, green, black (prototype's colors)
function message(line) {
document.getElementById('messageBox').innerHTML += line + '<br>';
}
body {
font-family: sans-serif;
}
<div id="messageBox"></div>
我在此代码段中使用了原型继承:
function SuperType() {
this.colors = ["red", "blue", "green"];
this.x = 1;
}
function SubType() {}
SubType.prototype = new SuperType();
var instance1 = new SubType();
instance1.colors.push("black");
instance1.x = 2;
//alert(instance1.colors); // "red,blue,green,black"
//alert(instance1.x); // 2
var instance2 = new SubType();
alert(instance2.colors); // "red,blue,green,black"
alert(instance2.x); // 1
我希望输出是
"red,blue,green"
1
或
"red,blue,green,black"
2
但我得到:
"red,blue,green,black"
1
为什么?
问题出在这里:
SubType.prototype = new SuperType();
因为SuperType
构造函数把.colors
数组放在对象上,又因为对象作为SubType
的.prototype
,所以.colors
数组在所有 SubType
个实例之间共享。
相反,在设置继承时不要调用构造函数,而是 do 在 SubType
构造函数中调用它。
function SubType() {
SuperType.apply(this, arguments);
}
SubType.prototype = Object.create(SuperType.prototype);
.x
没有同样问题的原因是数字不可变,因此当您尝试修改它时,会直接在对象上创建一个新的 x
重新使用而不是改变 .prototype
.
当您 运行 .push("black")
时,您正在使用一种修改对象(颜色列表)的方法;所以指向该对象的所有变量都会看到变化。
当您使用 = 2
时,您正在替换那个变量的值,因此其他变量仍然可以指向原始值。
写的时候
instance1.x = 2;
您正在向 instance1
添加一个名为 x
的新 属性。
instance1
的原型,你可以用instance1.__proto__
查找,不受影响。 instance1.__proto__.x
的值还是1。
当你参考
instance1.x
对象自身的 属性 instance1.x
优先于原型的 属性 instance1.__proto__.x
。我们说 x
on instance1
shadows x
on instance1.__proto__
.
当 JavaScript 计算 instance1.x
时,它会在向上移动原型链之前检查 instance1
自己的属性。所以,自己的值属性instance1.x
就是你看到的
但是当你写的时候
instance1.colors
对象 instance1
没有自己的 属性 称为 colors
。所以,JavaScript看它的原型。它找到 instance1.__proto__.colors
和 returns 其当前值。
你写的时候
instance1.colors.push("black");
您没有向 instance1
添加新的 属性。您只是修改了数组 instance1.__proto__.colors
。具有相同原型的所有对象都将看到相同的 colors
值,除非它们具有遮蔽 colors
.
在下面的代码片段中,我创建了第三个对象 c
,它定义了一个名为 colors
的自己的 属性,它隐藏了原型的 属性 c.__proto__.colors
.
var c = new SubType();
c.colors = [ 'orange', 'purple' ];
自身的值 属性 c.colors
与原型的 属性 c.__proto__.colors
的数组不同。没有自己的 属性 colors
的对象将继续看到原型的 colors
.
function SuperType() {
this.colors = ["red", "blue", "green"];
this.x = 1;
}
function SubType() {}
SubType.prototype = new SuperType();
var a = new SubType();
a.colors.push("black");
a.x = 2;
message('a.colors: ' + a.colors.join(', ')); // red, blue, green, black (prototype's colors)
message('a.x: ' + a.x); // 2 (own property x)
message('a.__proto__.x: ' + a.__proto__.x); // 1 (prototype's x)
var b = new SubType();
message('b.colors: ' + b.colors.join(', ')); // red, blue, green, black (prototype's colors)
message('b.x: ' + b.x); // 1 (prototype's x)
var c = new SubType();
// Make an own property, colors, that shadows the prototype's property.
c.colors = [ 'orange', 'purple' ];
message('c.colors: ' + c.colors.join(', ')); // orange, purple (own property colors)
message('b.colors: ' + b.colors.join(', ')); // red, blue, green, black (prototype's colors)
message('a.colors: ' + a.colors.join(', ')); // red, blue, green, black (prototype's colors)
function message(line) {
document.getElementById('messageBox').innerHTML += line + '<br>';
}
body {
font-family: sans-serif;
}
<div id="messageBox"></div>