Вы ошибаетесь. Будет только вызван конструктор родительского объекта. Методы будут унаследованы через прототип.
И снова неправда. И снова кусок кода, в качестве подтверждения моих слов:
// Объект-конструктор "Отец"
function Father() {
this.returnRed = function() {
return "red";
};
}
// Объект конструктор "Сын"
function Son() {
this.number = 1;
Father.call(this); // Делаем "наследование" через call
}
// Объект конструктор "Дочь"
function Daughter() {
this.number = 2;
}
father = new Father(); // Создаем экземпляр отца
Daughter.prototype = father; // Дочь наследует метод отца через прототип
son = new Son(); // Создаем экземпляр сына
daughter = new Daughter(); // Создаем экземпляр дочери
console.log(daughter.returnRed()); // red — метод унаследован
console.log(son.returnRed()); // red — неужели тоже унаследован?
// Изменяем метод в прототипе.
Daughter.prototype.returnRed = function() {
return "blue"
};
Son.prototype.returnRed = function() {
return "blue"
};
console.log(daughter.returnRed()); // blue — изменилось корректно
console.log(son.returnRed()); // red — опа! А метод то берется не из прототипа. Он просто скопировался в наш объект.
В вашей статье вы об этом не писали. Вы просто показали «более правильный» метод наследования, который, как я показал, не работает. Объект father не унаследовал свойство color, которое біло обїявлено в конструкторе Grandfather.
Кстати, вариант с Grandfather.call(this); в конструкторе тоже имеет недостатки, так как он скопирует методы родителя, вместо того, чтобы унаследовать их через прототип.
Нет. В итоге Father унаследует все от прототипа Grandfater, в нашем случае — Object. То есть не унаследует вообще ничего. Это я показал на примере в своем комментарии выше.
Если в конструкторе Grandfather будет alert или подобное добро, то как вы думаете сработает ли он в Father.prototype = new Grandfather();? ;-)
Если вы написали в конструкторе alert, то вы плохой программист. Если вы придерживаетесь следующего правила:
Я предпочитаю основываться на соглашениях и не проверяю this внутри конструктора — вызвал конструктор без new и поэтому утекло в глобалы — значит «сам дурак»
к клиентскому коду, то почему оно не распространяется на код ваших объектов?
function inherit (object, parent) {
function F(){}; // Подставной конструктор
F.prototype = parent.prototype; // Подсовываем прототип реального конструктора
object.prototype = new F(); // Теперь реальный конструктор не будет выполнен
return object; // Можно и не возвращать
};
function Grandfather() {
this.color = "red";
}
function Father() {
this.number = 1;
}
inherit(Father, Grandfather);
father = new Father();
console.log(father.number); // 1
console.log(father.color); // undefined
Вместо прямого указания, что прототипом конструктора Father, является экземпляр конструктора Grandfather, мы указываем пустой подставной объект. А прототип этого подставного объекта является прототипом конструктора Grandfather. То есть, если убрать подставной объект, получается что-то вроде
Father.prototype = Grandfather.prototype;
, что совсем не эквивалентно
Father.prototype = new Grandfather();
, так как если Grandfather это «самый верхний» объект в дереве, то его прототипом является Object.
В данном случае, мы как бы скопировали всю функцию, включая список аргументов и тело, и присвоили получившийся объект свойству make объекта arrayMaker. Это равносильно такому объявлению: var arrayMaker = {
someProperty: 'Какое-то значение';
make: function (arg1, arg2) {
return [ this, arg1, arg 2];
}
};
Не скопировали, а присвоили ссылку на созданную функцию новой переменной. И это не равносильно такому объявлению, так как в нем как раз создается новая аналогичная функция.
Пы.Сы. Заголовок звучит как «Пять способов вызвать функцию», хотя описано только четыре (если конечно apply и call не считаются двумя принципиально разными способами).
Ну это уже «на любителя». Мне самому как-то привычнее добавлять, чем доверять программе с подозрительным названием.
Слово «tweak» в названии программы всегда меня настораживало :)
Проект, ставший успешным бизнесом, похож на бигмак. В нем есть котлета (основной продукт/технология), верхняя булка (аудитория, которой этот продукт нужен) и нижняя булка (как и какие проблемы аудитории продукт будет решать).
Я наверно что-то не то курю. При чем здесь бигмак?!
Кстати, вариант с Grandfather.call(this); в конструкторе тоже имеет недостатки, так как он скопирует методы родителя, вместо того, чтобы унаследовать их через прототип.
Если вы написали в конструкторе alert, то вы плохой программист. Если вы придерживаетесь следующего правила: к клиентскому коду, то почему оно не распространяется на код ваших объектов?
Вместо прямого указания, что прототипом конструктора Father, является экземпляр конструктора Grandfather, мы указываем пустой подставной объект. А прототип этого подставного объекта является прототипом конструктора Grandfather. То есть, если убрать подставной объект, получается что-то вроде , что совсем не эквивалентно , так как если Grandfather это «самый верхний» объект в дереве, то его прототипом является Object.
Или я что-то не так понял?
Пы.Сы. Заголовок звучит как «Пять способов вызвать функцию», хотя описано только четыре (если конечно apply и call не считаются двумя принципиально разными способами).
Как вы это определили? Дайте ссылку на статистику :)
Тоже очень хорошо вписывается в IT тематику хабра :)
Мы, что все в каких-то разных интернетах сидим и гугла не видим?
На английском.
Слово «tweak» в названии программы всегда меня настораживало :)
И да, не только из консоли.
Я наверно что-то не то курю. При чем здесь бигмак?!