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?
When you write
instance1.x = 2;
you are adding a new property called x
to instance1
.
The prototype of instance1
, which you can look up with instance1.__proto__
, is unaffected. The value of instance1.__proto__.x
is still 1.
When you refer to
instance1.x
the object's own property instance1.x
takes precedence over the prototype's property instance1.__proto__.x
. We say that the x
on instance1
shadows the x
on instance1.__proto__
.
When JavaScript evaluates instance1.x
, it checks the own properties of instance1
before moving up the prototype chain. Therefore, the value of the own property instance1.x
is what you see.
But when you write
instance1.colors
the object instance1
does not have an own property called colors
. Therefore, JavaScript looks at its prototype. It finds instance1.__proto__.colors
and returns its current value.
When you wrote
instance1.colors.push("black");
you did not add a new property to instance1
. You merely modified the array 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
.
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
.
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
. Objects that don't have an own property colors
will continue to see the value of the prototype's 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>