[英]Properties on a prototype being affected differently
I'm using prototype inheritance in this code snippet: 我在这段代码片段中使用了原型继承:
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
I expect the output to be 我期待输出
"red,blue,green"
1
or 要么
"red,blue,green,black"
2
but I get: 但我得到:
"red,blue,green,black"
1
Why? 为什么?
The problem is here: 问题出在这里:
SubType.prototype = new SuperType();
Because the SuperType
constructor puts the .colors
Array on the object, and because the object is used as the .prototype
of SubType
, that .colors
Array is shared between all SubType
instances. 因为
SuperType
构造函数将.colors
数组放在对象上,并且因为该对象用作SubType
的.prototype
,所以.colors
Array在所有SubType
实例之间共享。
Instead, don't invoke the constructor when setting up inheritance but do invoke it within the SubType
constructor. 取而代之的是,建立继承时,不要调用构造函数,但不要在内部调用其
SubType
的构造。
function SubType() {
SuperType.apply(this, arguments);
}
SubType.prototype = Object.create(SuperType.prototype);
The reason the .x
didn't have the same issue is that numbers are not mutable, so when you try to modify it, a new x
gets created directly on the object you're using instead of mutating the .prototype
. .x
没有相同问题的原因是数字不可变,所以当你尝试修改它时,会直接在你正在使用的对象上创建一个新的x
而不是改变.prototype
。
When you write 当你写作
instance1.x = 2;
you are adding a new property called x
to instance1
. 您正在向
instance1
添加一个名为x
的新属性。
The prototype of instance1
, which you can look up with instance1.__proto__
, is unaffected. instance1
的原型,你可以使用instance1.__proto__
,不受影响。 The value of instance1.__proto__.x
is still 1. instance1.__proto__.x
值仍为1。
When you refer to 当你提到
instance1.x
the object's own property instance1.x
takes precedence over the prototype's property instance1.__proto__.x
. 对象自己的属性
instance1.x
优先于原型的属性instance1.__proto__.x
。 We say that the x
on instance1
shadows the x
on instance1.__proto__
. 我们说
x
上instance1
阴影在x
上instance1.__proto__
。
When JavaScript evaluates instance1.x
, it checks the own properties of instance1
before moving up the prototype chain. 当JavaScript的评估
instance1.x
,它检查的自己的属性instance1
连升原型链之前。 Therefore, the value of the own property instance1.x
is what you see. 因此,您看到的属性
instance1.x
的值。
But when you write 但是当你写作
instance1.colors
the object instance1
does not have an own property called colors
. 对象
instance1
没有称为colors
的属性。 Therefore, JavaScript looks at its prototype. 因此,JavaScript会查看其原型。 It finds
instance1.__proto__.colors
and returns its current value. 它找到
instance1.__proto__.colors
并返回其当前值。
When you wrote 你写的时候
instance1.colors.push("black");
you did not add a new property to instance1
. 您没有向
instance1
添加新属性。 You merely modified the array instance1.__proto__.colors
. 你只是修改了数组
instance1.__proto__.colors
。 All objects that have the same prototype will see the same value of colors
unless they have a property that shadows colors
. 具有相同原型的所有对象将看到相同的
colors
值,除非它们具有阴影colors
的属性。
In the code snippet below, I have made a third object, c
, that defines an own property called colors
, which shadows the prototype's property c.__proto__.colors
. 在下面的代码片段中,我创建了第三个对象
c
,它定义了一个名为colors
的属性,它隐藏了原型的属性c.__proto__.colors
。
var c = new SubType();
c.colors = [ 'orange', 'purple' ];
The value of the own property c.colors
is a different array than the prototype's property c.__proto__.colors
. 自己的属性
c.colors
的值是与原型的属性c.__proto__.colors
不同的数组。 Objects that don't have an own property colors
will continue to see the value of the prototype's 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"); ax = 2; message('a.colors: ' + a.colors.join(', ')); // red, blue, green, black (prototype's colors) message('ax: ' + ax); // 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('bx: ' + bx); // 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>
When you run .push("black")
you are using a method that modifies the object (the list of colours) in place; 当您运行
.push("black")
您正在使用一种方法来修改对象(颜色列表); so all variables pointing at that object see the change. 所以指向该对象的所有变量都会看到变化。
When you use = 2
, you are replacing the value of that one variable, so other variables can still point at the original value. 当您使用
= 2
,您将替换该一个变量的值,因此其他变量仍然可以指向原始值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.