Как известно, методы «класса» в JavaScript лучше всего определять на прототипе, а свойства — на конструкторе, потому что методы нежелательно дублировать, определяя заново в каждом объекте, а значения свойств должны быть уникальны для каждого объекта.
Как же реализовать наследование?
Концепция наследования через цепь прототипов
Можно реализовать наследование через цепочку прототипов. Объявляются два «класса», прототип «потомка» объявляется как новый объект, созданный вызовом конструктора «родителя». Вот так:
function SuperType(){ } function SubType(){ } SubType.prototype = new SuperType();
Такой подход создаёт только две проблемы:
1. Ссылочные значения делятся между всеми «потомками» «родителя».
2. Нельзя передать аргументы конструктору «родителя».
Способ, предложенный в книге JavaScript Allongé:
Берем суперкласс Superclass, объявляем для него пустой прокси-класс:
var SuperclassProxy = function () { this.constructor = Subclass; } SuperclassProxy.prototype = Superclass.prototype
Далее мы используем конструктор прототипа суперкласса в конструкторе класса-потомка. В качестве прототипа класса-потомка используем конструктор прокси-класса. Сам прокси-класс нужен, чтобы случайно не испортить что-нибудь в суперклассе при вызове его конструктора. Например, если в конструкторе выполняется подключение к БД, то не выполнять его при каждом наследовании.
var Subclass = function () { Superclass.prototype.constructor.call(this) }; Subclass.prototype = new SuperclassProxy();
Далее мы делаем копию объекта (shallow copy) Superclass и дополняем ее методами и свойствами Subclass.
Решение, предложенное в книге Effective JavaScript:
Допустим, у нас есть SuperType, и мы пытаемся создать SubType на его основе.
function SubType(arg1, arg2, arg3) { SuperType.call ( this, arg1, arg2, arg3); // разные действия в собственно конструкторе SubType } SubType.prototype = Object.create(SuperType.prototype); // наследуем прототип
Здесь мы сначала вызываем конструктор SuperType, передавая туда все требуемые аргументы, а в качестве приёмника будет SubType.
Затем наследуем прототип SuperType.