You cannot change a constructor by reassigning to prototype.constructor
What is happening is that Rabbit.prototype.constructor
is a pointer to the original constructor (function Rabbit(){...}
), so that users of the 'class' can detect the constructor from an instance. Therefore, when you try to do:
Rabbit.prototype.constructor = function Rabbit() {
this.jumps = "no";
};
You're only going to affect code that relies on prototype.constructor
to dynamically instantiate objects from instances.
When you call new X
, the JS engine doesn't reference X.prototype.constructor
, it uses the X
as the constructor function and X.prototype
as the newly created object's prototype., ignoring X.prototype.constructor
.
A good way to explain this is to implement the new
operator ourselves. ( Crockford will be happy, no more new ;)
// `new` emulator
//
// Doesn't reference `.constructor` to show that prototype.constructor is not used
// when istantiating objects a la `new`
function make(ctorFun, argsArray) {
// New instance attached to the prototype but the constructor
// hasn't been called on it.
const newInstance = Object.create(ctorFun.prototype);
ctorFun.apply(newInstance, argsArray);
return newInstance;
}
// If you create a utility function to create from instance, then it uses the
// inherited `constructor` property and your change would affect that.
function makeFromInstance(instance, argsArray) {
return make(instance.constructor, argsArray);
}
function X(jumps) {
this.jumps = jumps;
}
// Flip the constructor, see what it affects
X.prototype.constructor = function(jumps) {
this.jumps = !jumps;
}
const xFromConstructorIsGood = make(X, [true]);
const xFromInstanceIsBad = makeFromInstance(xFromConstructorIsGood, [true]);
console.log({
xFromConstructorIsGood,
xFromInstanceIsBad
});
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…