Чтобы наследовать от другого объекта Javascript, в частности от EventEmitter Node.js, но на самом деле от любого объекта в целом, вам нужно сделать две вещи:
- предоставляет конструктор для вашего объекта, который полностью инициализирует объект; в случае если вы наследуете какой-то другой объект, вы, вероятно, захотите делегировать часть этой работы по инициализации супер-конструктору.
- предоставляет объект-прототип, который будет использоваться как
[[proto]]
для объектов, созданных из вашего конструктора; в случае если вы наследуете какой-то другой объект, вы, вероятно, захотите использовать экземпляр другого объекта в качестве прототипа.
В Javascript это сложнее, чем в других языках, потому что
- Javascript разделяет поведение объекта на «конструктор» и «прототип». Эти понятия предназначены для совместного использования, но могут использоваться отдельно.
- Javascript - это очень податливый язык, и люди используют его по-разному, и нет единого истинного определения того, что означает «наследование».
- Во многих случаях вы можете сойтись с подмножеством того, что правильно, и вы найдете множество примеров для подражания (включая некоторые другие ответы на этот вопрос SO), которые, кажется, хорошо работают для вашего случая.
Для конкретного случая EventEmitter Node.js вот что работает:
var EventEmitter = require('events').EventEmitter;
var util = require('util');
// Define the constructor for your derived "class"
function Master(arg1, arg2) {
// call the super constructor to initialize `this`
EventEmitter.call(this);
// your own initialization of `this` follows here
};
// Declare that your class should use EventEmitter as its prototype.
// This is roughly equivalent to: Master.prototype = Object.create(EventEmitter.prototype)
util.inherits(Master, EventEmitter);
Возможные недостатки:
- Если вы используете набор прототипов для своего подкласса (Master.prototype), с или без использования
util.inherits
, но не вызываете супер-конструктор (EventEmitter
) для экземпляров вашего класса, они не будут правильно инициализирован.
- Если вы вызываете супер-конструктор, но не устанавливаете прототип, методы EventEmitter не будут работать с вашим объектом
- Вы можете попытаться использовать инициализированный экземпляр суперкласса (
new EventEmitter
) как Master.prototype
вместо того, чтобы конструктор подкласса Master
вызывал конструктор суперкласса EventEmitter
; в зависимости от поведения конструктора суперкласса, который может казаться, что он некоторое время работает нормально, но это не одно и то же (и не будет работать для EventEmitter).
- Вы можете попытаться использовать супер-прототип напрямую (
Master.prototype = EventEmitter.prototype
) вместо добавления дополнительного слоя объекта через Object.create; может показаться, что он работает нормально, пока кто-то не установит обезьяны на ваш объект Master
и случайно не пропустит обезьяну EventEmitter
и всех других его потомков. У каждого «класса» должен быть свой прототип.
Опять же: чтобы наследовать от EventEmitter (или действительно любого существующего "класса" объекта), вы хотите определить конструктор, который связан с супер-конструктором и предоставляет прототип, производный от супер-прототипа.