Вы не можете изменить конструктор, переназначив его на prototype.constructor
. Происходит следующее: Rabbit.prototype.constructor
является указателем на исходный конструктор (function Rabbit(){...}
), так что пользователи «класса» могутобнаружить конструктор из экземпляра.Поэтому, когда вы попытаетесь сделать:
Rabbit.prototype.constructor = function Rabbit() {
this.jumps = "no";
};
Вы будете влиять только на код, который опирается на prototype.constructor
для динамического создания объектов из экземпляров.
Когда вы вызываете new X
, механизм JS не ссылается на X.prototype.constructor
, он использует X
в качестве функции конструктора и X.prototype
в качестве прототипа вновь созданного объекта., Игнорируя X.prototype.constructor
.
Хороший способ объяснить это - реализовать оператор 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
});
Наследование в JS
Библиотеки, которые помогают с наследованием JS, реализуют наследование и полагаются на prototype.constructor
с чем-то в духеследующее:
function extend(base, sub) {
function surrogateCtor() {}
// Copy the prototype from the base to setup inheritance
surrogateCtor.prototype = base.prototype;
sub.prototype = new surrogateCtor();
// The constructor property is set to the base constructor
// with the above trick, let's fix it
sub.prototype.constructor = sub;
}
Вы можете видеть, что в приведенном выше коде мы должны исправить свойство конструктора, поскольку оно иногда используется для создания экземпляра объекта, когда у вас есть только экземпляр.но это не влияет на фактический конструктор.См. Мой пост о наследовании JS http://js -bits.blogspot.com / 2010/08 / javascript-inheritance-done-right.html
Как переопределить конструктор Если вы действительно хотите переопределить конструктор, просто выполните
// If Rabbit had any custom properties on it
// (or static properties as some call it), they would not be copied, you'd have to do that manually using getOwnPropertyNames
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames
var oldProto = Rabbit.prototype;
Rabbit = function() {...};
Rabbit.prototype = oldProto;
Обратите внимание, что это не повлияет на код, который уже скопировал эту ссылку, например:
const myRefRabbit = Rabbit