2011-07-31 7 views
5

私はEventEmitterで遊んでいましたが、モジュールからどのように実装するべきかについて混乱しています。私はいくつかの異なる方法を見てきました。そして、それらはすべて動作するようです。Node.js - モジュールからイベントを放出する最良の方法

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

Twitter.prototype = new events.EventEmitter; 

しかし、その後"Mastering Node"に、彼らはそれをこのように実行します:hereから

:ここで私が見てきたいくつかある

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

Dog.prototype.__proto__ = EventEmitter.prototype; 

(なぜあなたはそれをは.callする必要があるでしょうか? )

そして私のコードでは、私はまだ別の方法を試みました:

function Class() {} 

Class.prototype = EventEmitter.prototype; 

彼らはすべて独自の方法でEventEmitterから継承しているので、最も簡単な解決策は最高ではありませんか?

答えて

18

__proto__継承スタイルを使用する必要があります。 This assumes you're coding solely for Node, or only supporting your favorite browsers。また、基本プロトタイプのコンストラクタのロジックを気にする場合は、Base.call(this)が必要です。

基本プロトタイプを参照するテクニックは、instanceofオペレータがプロトタイプのインスタンスを正しく識別できるようにします。子クラスのインスタンスの.constructorプロパティは、期待するコンストラクタを参照します。基本プロトタイプの新しいインスタンスをインスタンス化しないという利点もあります。

new Base()スタイルでも、正しい答えが得られますが、Baseのコンストラクタが実行されます。一般的には問題ではありませんが、基本コンストラクタに引数が必要な場合は問題になることがあります。また、.constructorプロパティをベースコンストラクタのnot the descendant constructorに設定します。ベースのいずれかの子孫は、子のインスタンスであるかのように見えますようにベースクラスのプロトタイプにごクラスのプロトタイプを設定

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

ワウありがとう。私はこの答えに複数のアップヴォートを与えることができたらいいと思う。 –

20

ノードにはutil.inheritsというライブラリ関数があり、それは受け入れられた答えよりやや簡単です。下記のコードはv0.8.12 docsから変更されています。

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

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

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

これには多少関連する[この質問](http://stackoverflow.com/questions/24809786/different-ways-of-extending-classes-in-node-js)があります。それを見てもらえますか? – majidarif

+0

また、 'events.EventEmitter.call(this);'について説明し、なぜこれが必要なのか、それを無視することができるのでしょうか? – majidarif

+1

@majidarif簡単な答えは、呼び出しがMyStreamインスタンスを "this"変数としてEventEmitter関数を実行するため、MyStreamインスタンスのすべてのEventEmitter初期化を実行することです。希望は意味をなさない。 – bmavity

関連する問題