Let us begin with a distracted example:var a = {
test: 11
}
b = a;
b.test = 12;
console.log(a.test); // Выведет 12!This is because objects in JS are assigned and transferred by reference Not by weight.Sovereignty <An Object>.prototype - it's an object. When you do the code:Bar.prototype = Foo.prototype;
you're assigning the properties Bar.prototype reference on site Foo.prototype♪ As a consequence, any change in properties Bar.prototype Change Foo.prototypequoted in the quote:This means when you start assigning, like Bar.prototype.myLabel = ..., you're modifying not a separate object but the shared Foo.prototype object itself, which would affect any objects linked to Foo.prototype.Small Lire derogation♪Actually, I'd recommend you. Never Not to use design:Bar.prototype = new Foo();
And all those who advise you are brave. send the JS framework.♪ All the salt is that new Foo() You're calling the object designer. In doing so, the designer itself may, on the one hand, impose restrictions on the arguments transmitted and on the other, have side effects. We'll figure out each of these cases separately.Let's say you have this designer that puts restrictions on your arguments:Foo = function(a) {
if (typeof a === 'undefined') {
throw new Error('You have to set the first argument.');
}
this.a = a;
}
In this case, you can't just take and execute:Bar.prototype = new Foo();
That is, you need to make a clear argument to the designer, which makes no sense at the time of the hierarchy of the inheritance. The interesting thing is the parameter value. a It'll be lost when the designer is called. Foo in the pre-school designer. Bar♪ So construction new Foo() It makes no sense.Now we suggest that the parent designer has side effects:Foo = function(a) {
console.log('Here I am!');
}
When used:Bar.prototype = new Foo();
and beyond:var Bar = function() {
Foo.call(this);
}
line "Here I am!"to be out. twice.♪ Agree, this is not always the desired behaviour of the system.Well, there's another curious fact, even if Right now. The parent designer has no side effects or limitations on arguments, which doesn't mean he's gonna like this. forever♪ It's better to do it right now than to get the code straight in the search for a mistake when it's all broken.I'll get you a background check, correct implementation Inheritance in JS:// Базовый конструктор
var Foo = function() {
// ...
};
Foo.prototype.doSomething = function() {
// ...
};
// Дочерний конструктор
var Bar = function() {
// Вызываем базовый конструктор для текущего объекта.
Foo.call(this);
// ...
};
// Устанавливаем правильное значение в цепочке прототипов.
Bar.prototype = Object.create(Foo.prototype, {
// Выставляем правильную функцию-конструктор для всех создаваемых
// объектов.
constructor: {
value: Bar,
enumerable: false,
writable: true,
configurable: true
}
});
// Расширяем прототип дочернего "класса". Этот шаг должен идти
// СТРОГО ПОСЛЕ установки значения Bar.prototype.
Bar.prototype.doAnotherAction = function() {
// ...
};
In case you can't use Object.create (old browsers) you can either use one of the existing polyphiles or make all the pens (through anonymous designer):var inherits = function(ctor, superCtor) {
// Временный конструктор, который не делает ничего и нужен
// только для разрыва прямой связи между прототипами ctor
// и superCtor. Его использование позволяет менять прототип
// дочернего конструктора, не боясь сломать родительский.
var Tmp = function() {};
Tmp.prototype = superCtor.prototype;
// Обратите внимание, вызов new Tmp() не имеет АБСОЛЮТНО
// никаких побочных эффектов и не накладывает ограничений
// на передаваемые значения.
ctor.prototype = new Tmp();
// Выставляем правильную функцию-конструктор для всех
// создаваемых объектов.
ctor.prototype.constructor = ctor;
};
In view of the above, the universal function of inheritance may be:var inherits = (function() {
if (typeof Object.create === 'function') {
// Используем более простой вариант, если Object.create существует.
return function(ctor, superCtor) {
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
}
// Используем временный конструктор для старых браузеров
return function(ctor, superCtor) {
var Tmp = function() {};
Tmp.prototype = superCtor.prototype;
ctor.prototype = new Tmp();
ctor.prototype.constructor = ctor;
};
})();
UPD:In implementation above, after the prototype has been awarded, the properties shall be assigned https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor ♪ Although this characteristic is rarely used in practice (also I have never seen in the production of the code), the full realization of the inheritance must be displayed.