2011-07-31 12 views
5

He estado jugando con el EventEmitter, pero estoy confundido acerca de cómo exactamente debo implementarlo desde un módulo. He visto algunas maneras diferentes, y todas parecen funcionar. Aquí están algunos que he visto:Node.js - El mejor método para emitir eventos desde los módulos

De here:

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

Twitter.prototype = new events.EventEmitter; 

Pero entonces, en "Mastering Node" lo hacen de esta manera:

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

Dog.prototype.__proto__ = EventEmitter.prototype; 

(¿Por qué necesitaría para que .call?)

Y luego, en mi propio código que intentaron otra manera:

function Class() {} 

Class.prototype = EventEmitter.prototype; 

Todos heredan de EventEmitter a su manera, así que ¿no sería la solución más simple la mejor?

Respuesta

18

Debe usar el estilo de herencia __proto__. This assumes you're coding solely for Node, or only supporting your favorite browsers. Además, Base.call(this) es necesario si le importa cualquier lógica en el constructor de su prototipo base.

La técnica __proto__ para hacer referencia a un prototipo base garantizará que el operador instanceof identifique correctamente las instancias del prototipo. La propiedad .constructor de instancias del niño clase hará referencia al constructor que usted espera. También tiene la ventaja de no instanciar una nueva instancia del prototipo base.

El estilo new Base() también garantizará que instanceof le proporcione la respuesta correcta, pero ejecutará el constructor para Base. Generalmente no es un problema, pero puede ser problemático si su constructor base tiene argumentos requeridos. También establecerá la propiedad .constructor en el constructor base, not the descendant constructor.

Ajuste del prototipo de la claseal prototipo de la base de clase confundirá instanceof como cualquier descendiente de la base también aparecerá ser instancias del niño.

Claro como el barro, ¿verdad? Este ejemplo debería ayudar:

// 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. 
+1

Wow gracias. Desearía poder dar más de un voto positivo para esta respuesta. –

20

nodo tiene una función de biblioteca, util.inherits, que es un poco más sencillo que la respuesta aceptada. El siguiente código se modifica desde el v0.8.12 docs.

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

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

util.inherits(MyStream, events.EventEmitter); 
+0

Tengo [esta pregunta] (http://stackoverflow.com/questions/24809786/different-ways-of-extending-classes-in-node-js) que está relacionada de alguna manera con esto. ¿Te importaría mirarlo? – majidarif

+0

También podría explicar 'events.EventEmitter.call (this);' y ¿por qué es necesario o si es posible ignorarlo? – majidarif

+1

@majidarif La respuesta corta es que la llamada ejecuta la función EventEmitter con la instancia de MyStream como la variable "this", por lo que pasará por todas las inicializaciones de EventEmitter para las instancias de MyStream. Espero que tenga sentido. – bmavity

Cuestiones relacionadas