原型上的属性受到不同的影响

时间:2015-12-27 23:42:01

标签: javascript inheritance prototype prototypal-inheritance prototype-programming

我在此代码段中使用原型继承:

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

为什么?

3 个答案:

答案 0 :(得分:4)

问题在于:

SubType.prototype = new SuperType();

因为SuperType构造函数将.colors数组放在对象上,并且因为该对象用作.prototype的{​​{1}},所以SubType数组在所有.colors个实例之间共享。

相反,在设置继承时不要调用构造函数,但执行SubType构造函数中调用它。

SubType

function SubType() { SuperType.apply(this, arguments); } SubType.prototype = Object.create(SuperType.prototype); 没有相同问题的原因是数字不可变,所以当您尝试修改它时,会直接在对象上创建新的.x&# 39;重新使用而不是改变x

答案 1 :(得分:1)

写作时

instance1.x = 2;

您要向x添加名为instance1的新媒体资源。

instance1的原型,您可以使用instance1.__proto__查找,不受影响。 instance1.__proto__.x的值仍为1.

当您参考

instance1.x

对象自己的属性instance1.x优先于原型的属性instance1.__proto__.x。我们说x上的instance1 阴影 x上的instance1.__proto__

当JavaScript评估instance1.x时,它会在升级原型链之前检查instance1的自身属性。因此,您看到的是自己的属性instance1.x的值。

但是当你写作

instance1.colors

对象instance1没有名为colors的属性。因此,JavaScript会查看其原型。它找到instance1.__proto__.colors并返回其当前值。

当你写

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>

答案 2 :(得分:0)

当您运行XHRCallToTheRestService() .then(function(result){ //Hide status bar, data is back }); readMyStatus() .then(function(status){ if(status == "finished"){ //Do nothing } else{ readMyStatus(); } }); 时,您正在使用一种方法来修改对象(颜色列表);所以指向该对象的所有变量都会看到变化。

当您使用.push("black")时,您正在替换该一个变量的值,因此其他变量仍然可以指向原始值。