Node.js - лучший метод для генерации событий из модулей - PullRequest
5 голосов
/ 01 августа 2011

Я играл с EventEmitter, но меня смущает, как именно я должен реализовать его из модуля. Я видел несколько разных способов, и все они, кажется, работают. Вот несколько, которые я видел:

С здесь :

var Twitter = function() {...};

Twitter.prototype = new events.EventEmitter;

Но затем в «Узле мастеринга» они делают это так:

function Dog(name) {
  this.name = name;
  EventEmitter.call(this);
}

Dog.prototype.__proto__ = EventEmitter.prototype;

(зачем вам звонить?)

А потом в своем собственном коде я попробовал еще один способ:

function Class() {}

Class.prototype = EventEmitter.prototype;

Они все просто наследуют от EventEmitter по-своему, поэтому самое простое решение не будет лучшим?

Ответы [ 2 ]

20 голосов
/ 14 октября 2012

Узел имеет библиотечную функцию util.inherits, которая несколько проще, чем принятый ответ. Код ниже модифицируется из v0.8.12 документов .

var util = require("util");
var events = require("events");

function MyStream() {
  events.EventEmitter.call(this);
}

util.inherits(MyStream, events.EventEmitter);
18 голосов
/ 02 августа 2011

Вы должны использовать стиль наследования __proto__. Предполагается, что вы пишете только для Node или поддерживаете только свои любимые браузеры .Кроме того, Base.call(this) необходимо, если вы заботитесь о какой-либо логике в конструкторе базового прототипа.

Метод __proto__ для ссылки на базовый прототип гарантирует, что оператор instanceof правильно идентифицирует экземплярыпрототип.Свойство .constructor экземпляров дочернего элемента class будет ссылаться на ожидаемый конструктор.Это также имеет то преимущество, что не создает экземпляр нового экземпляра базового прототипа.

Стиль new Base() также гарантирует, что instanceof даст вам правильный ответ, но он запустит конструктор для Base.Обычно это не проблема, но может быть проблематично, если ваш базовый конструктор имеет требуемые аргументы.Также будет установлено свойство .constructor для базового конструктора, не для конструктора-потомка .

Установка прототипа вашего класса на прототип базовой class будет путать instanceof, поскольку любые потомки базы также будут являться экземплярами ребенка.

Чисто как грязь, верно?Этот пример должен помочь:

// Base constructor.
// A, B, and C will inherit from Base.
function Base() {
    this.name = 'base';
}

// new Base() style
function A() {
    Base.call(this);
}
A.prototype = new Base();

// __proto__ = prototype style
function B() {
    Base.call(this);
}
B.prototype.__proto__ = Base.prototype;

// prototype = protoype style
function C() {
    Base.call(this);
}
C.prototype = Base.prototype;

// create instances
var a = new A();
var b = new B();
var c = new C();

// are we who we think we are?
console.assert(a instanceof A);
console.assert(b instanceof B);
console.assert(c instanceof C);
// so far so good

// do we respect our elders?
console.assert(a instanceof Base);
console.assert(b instanceof Base);
console.assert(c instanceof Base);
// we have respect

// test to see that Base.call(this)
// functioned as expected
console.assert(a.name == 'base');
console.assert(b.name == 'base');
console.assert(c.name == 'base');
// ok, good...

// but now things get weird
console.assert(a instanceof C);
console.assert(b instanceof C);
// that's not right! a is not C, b is not C!

// At least A and B do not confuse identities
console.assert(!(a instanceof B));
console.assert(!(b instanceof A));

console.assert(!(c instanceof A));
console.assert(!(c instanceof B));

// so we've determined that style C is no good.
// C confuses the inheritance chain.

// B is the winner.

// Why? Only B passes this test
console.assert(b.constructor == B);

// a and c's constructors actually point to the Base constructor
console.assert(a.constructor == Base);
console.assert(c.constructor == Base);

// Word B.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...