I'm trying to improve my knowledge on object, constructors, prototype and all that stuff related to objects in JS. I was reading a post on MDN about inheritance and the prototype chain and I came across this explanation about why you should not reassign the Constructor.prototype after you created the instances. I cannot understand what those two reasons mean:
function Box(value) {
this.value = value;
}
Box.prototype.getValue = function () {
return this.value;
};
const box = new Box(1);
// Mutate Box.prototype after an instance has already been created
Box.prototype.getValue = function () {
return this.value + 1;
};
box.getValue(); // 2
Their explanation:
A corollary is, re-assigning Constructor.prototype
(Constructor.prototype = ...
) is a bad idea for two reasons:
The [[Prototype]]
of instances created before the reassignment is now referencing a different object from the [[Prototype]]
of instances created after the reassignment — mutating one's [[Prototype]]
no longer mutates the other.
Unless you manually re-set the constructor
property, the constructor function can no longer be traced from instance.constructor
, which may break user expectation. Some built-in operations will read the constructor
property as well, and if it is not set, they may not work as expected.
The article is referring to this behavior:
function Box(value) {
this.value = value;
}
Box.prototype.getValue = function () {
return this.value;
};
const box1 = new Box(1);
// Mutate Box.prototype after an instance has already been created
Box.prototype = {
getValue() {
return this.value + 42;
}
}
const box2 = new Box(1);
console.log(box1.getValue()); // 2
console.log(box2.getValue()); // 43
If you assign a new value to Box.prototype
then only newly created instances will have this new value as their prototype. Mutating the existing prototype object as in your example is not a problem (but still not common).
Unless you manually re-set the
constructor
property, the constructor function can no longer be traced frominstance.constructor
...
Compare the following
function Box(value) {
this.value = value;
}
const box1 = new Box(1);
console.log('box1.constructor === Box:', box1.constructor === Box);
Box.prototype = {
getValue() {
return this.value + 42;
}
}
const box2 = new Box(1);
console.log('box2.constructor === Box:', box2.constructor === Box);
Box.prototype = {
constructor: Box,
getValue() {
return this.value + 42;
}
}
const box3 = new Box(1);
console.log('box3.constructor === Box:', box3.constructor === Box);
Unless constructor
is explicitly set after assigning to Box.prototype
, box.constructor
does not refer to Box
.
This might useful: