2011-07-31 10 views
5

Grałem z EventEmitter, ale nie wiem, jak dokładnie powinienem go wdrożyć z modułu. Widziałem kilka różnych sposobów i wszystkie wydają się działać. Oto kilka z nich widziałem:Node.js - Najlepsza metoda emisji zdarzeń z modułów

Od here:

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

Twitter.prototype = new events.EventEmitter; 

ale potem w "Mastering Node" robią to w ten sposób:

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

Dog.prototype.__proto__ = EventEmitter.prototype; 

(dlaczego trzeba go .Połączenia?)

A następnie w moim własnym kodzie próbowałam jeszcze innego sposobu:

function Class() {} 

Class.prototype = EventEmitter.prototype; 

Po prostu dziedziczą po EventEmitter na swój sposób, więc czy najprostsze rozwiązanie nie byłoby najlepsze?

Odpowiedz

18

Powinieneś używać stylu dziedziczenia . This assumes you're coding solely for Node, or only supporting your favorite browsers. Ponadto, jeśli interesuje cię jakakolwiek logika w konstruktorze twojego podstawowego prototypu, konieczny jest Base.call(this).

Technika odniesienia do prototypu podstawowego zapewni, że operator instanceof poprawnie identyfikuje wystąpienia prototypu. Właściwość .constructor instancji dziecka klasa odwoła się do konstruktora, którego się spodziewasz. Ma także tę zaletę, że nie tworzy instancji podstawowego prototypu.

Styl new Base() zapewnia również, że instanceof daje poprawną odpowiedź, ale uruchomi konstruktor dla bazy. Zwykle nie jest to problem, ale może być problematyczne, jeśli twój bazowy konstruktor ma wymagane argumenty. Ustawi także właściwość .constructor dla konstruktora bazowego, not the descendant constructor.

Ustawianie prototyp klasydo prototypu bazowej klasy pomyli instanceof jak każdy potomków podstawy również pojawią się przypadki dziecka.

Wyczyść jak błoto, prawda? Ten przykład powinien pomóc:

// 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, dziękuję. Chciałbym móc udzielić więcej niż jednego przegłosowania tej odpowiedzi. –

20

Węzeł ma funkcję biblioteczną, util.inherits, która jest nieco bardziej bezpośrednia niż zaakceptowana odpowiedź. Poniższy kod został zmodyfikowany z v0.8.12 docs.

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

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

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

Mam [to pytanie] (http://stackoverflow.com/questions/24809786/different-ways-of-extending-classes-in-node-js), który jest nieco związany z tym. Czy mógłbyś na to spojrzeć? – majidarif

+0

Czy mógłbyś wytłumaczyć również 'events.EventEmitter.call (this);' i dlaczego jest to konieczne lub czy można go zignorować? – majidarif

+1

@majidarif Krótka odpowiedź jest taka, że ​​wywołanie wykonuje funkcję EventEmitter z instancją MyStream jako "tą" zmienną, więc przechodzi przez całą inicjalizację EventEmitter dla instancji MyStream. Mam nadzieję, że ma to sens. – bmavity

Powiązane problemy