Книга: JavaScript. Подробное руководство, 6-е издание
9.6.5. Заимствование методов
9.6.5. Заимствование методов
В методах JavaScript нет ничего необычного - это обычные функции, присвоенные свойствам объекта и вызываемые «посредством» или «в контексте» объекта.
Одна и та же функция может быть присвоена двум свойствам и играть роль двух методов. Мы использовали эту возможность в нашем классе Set
, например, когда скопировали метод toArray()
и заставили его играть вторую роль в виде метода toJSON()
.
Одна и та же функция может даже использоваться как метод сразу нескольких классов. Большинство методов класса Array
, например, являются достаточно универсальными, чтобы копировать их из Array.prototype
в прототип своего класса, экземпляры которого являются объектами, подобными массивам. Если вы смотрите на язык JavaScript через призму классических объектно-ориентированных языков, тогда использование методов одного класса в качестве методов другого класса можно рассматривать как разновидность множественного наследования. Однако JavaScript не является классическим объектно-ориентированным языком, поэтому я предпочитаю обозначать такой прием повторного использования методов неофициальным термином заимствование.
Заимствоваться могут не только методы класса Array
: мы можем реализовать собственные универсальные методы. В примере 9.9 определяются обобщенные методы toString()
и equals(),
которые с успехом могут использоваться в таких классах, как Range, Complex
и Card
. Если бы класс Range не имел собственного метода equals(),
мы могли бы заимствовать обобщенный метод equals()
, как показано ниже:
Range.prototype.equals = generic.equals;
Обратите внимание, что метод generic.equals()
выполняет лишь поверхностное сравнение и не подходит для использования в классах, свойства экземпляров которых ссылаются на объекты с их собственными методами equals().
Отметьте также, что этот метод включает специальный случай для обработки свойства, добавляемого к объектам при включении их в множество Set (пример 9.6).
Пример 9.9. Обобщенные методы, пригодные для заимствования
var generic = {
// Возвращает строку, включающую имя функции-конструктора, если доступно,
// и имена и значения всех неунаследованных свойств, не являющихся функциями.
toString: function() {
var s = '[';
// Если объект имеет конструктор и конструктор имеет имя, использовать
// это имя класса как часть возвращаемой строки. Обратите внимание, что
// свойство name функций является нестандартным и не поддерживается повсеместно,
if (this.constructor && this.constructor.name) s += this.constructor.name + ";
// Теперь обойти все неунаследованные свойства, не являющиеся функциями
var n = 0;
for(var name in this) {
if (!this.hasOwnProperty(name)) continue; // пропустить унаслед.
var value = this[name];
if (typeof value === ’function") continue; // пропустить методы
if (n++) s += ", ";
s += name + '=' + value;
}
return s + ']';
},
// Проверить равенство, сравнив конструкторы и свойства экземпляров объектов this
// и that. Работает только с классами, свойства экземпляров которых являются
// простыми значениями и могут сравниваться с помощью оператора ===.
// Игнорировать специальное свойство, добавляемое классом Set.
equals: function(that) {
if (that == null) return false;
if (this.constructor !== that.constructor) return false;
for(var name in this) {
if (name === "|**objectid**|") continue; // пропустить спец. св.
if (!this.hasOwnProperty(name)) continue; // пропустить унасл. св.
if (this[name] !== that[name]) return false; // сравнить значения
}
return true; // Объекты равны, если все свойства равны.
}
};
- Множественные интерфейсы и имена методов
- Перегрузка методов с несколькими параметрами типа
- Параметры методов
- Обзор методов асинхронного ввода
- 3. Узкий диапазон методов конкурентного взаимодействия
- 7.12. Динамическое назначение методов
- Обзор методов управления памятью
- Выбор методов лидгена
- Выбор инструментальных средств моделирования и методов
- 7.2. Классификация IPC-методов в Unix
- Выбор методов вывода
- Эффективность методов скрытого воздействия