使い方 - EventEmitter からの Node.js 継承



node js イベント 駆動 (4)

ES 6スタイルクラスの継承

これらはドキュメントからまっすぐに来ましたが、見ている人にこの人気のある質問にそれらを追加するといいと思いました。

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {
  constructor() {
    super(); //must call super for "this" to be defined.
  }     
}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('an event occurred!');
});
myEmitter.emit('event');

私は誰でもそれを追加したgit thankたいと思います。 イベントエミッタ

注意:ドキュメントはコンストラクタ内でsuper()を呼び出さないため、これは未定義になります。 このissue参照してください。

https://src-bin.com

私はかなりの数のNode.jsライブラリでこのパターンを見ています:

Master.prototype.__proto__ = EventEmitter.prototype;

hereソース)

誰かが私に例を挙げて説明してください、なぜこれが一般的なパターンなのか、それは便利なのでしょうか?


Answer #1

wprlの応答に追加する。 彼は "プロトタイプ"の部分を見逃した:

function EventedObject(){

   // Super constructor
   EventEmitter.call(this);

   return this;

}
EventObject.prototype = new EventEmitter(); //<-- you're missing this part

Answer #2

そのコードの上のコメントは、 MasterEventEmitter.prototypeから継承するようにするため、その 'クラス'のインスタンスを使用してイベントをEventEmitter.prototypeことができるようにします。

たとえば、次のようにすることができます。

masterInstance = new Master();

masterInstance.on('an_event', function () {
  console.log('an event has happened');
});

// trigger the event
masterInstance.emit('an_event');

アップデート :多くのユーザーが指摘しているように、Nodeでこれを行う「標準的な」方法は、 'util.inherits'を使用することです。

var EventEmitter = require('events').EventEmitter;
util.inherits(Master, EventEmitter);

Answer #3

他のJavascriptオブジェクトであるNode.jsのEventEmitterを継承するには、一般的にはオブジェクトですが、2つのことを行う必要があります。

  • オブジェクトを完全に初期化するオブジェクトのコンストラクタを提供します。 あなたが他のオブジェクトから継承している場合は、この初期化作業のいくつかをスーパーコンストラクタに委譲したいと思うでしょう。
  • コンストラクタから作成されたオブジェクトの[[proto]]として使用されるプロトタイプオブジェクトを提供します。 他のオブジェクトから継承している場合は、おそらく他のオブジェクトのインスタンスをプロトタイプとして使用することになります。

これはJavascriptでは他の言語と同じように複雑になります

  • Javascriptはオブジェクトの動作を「コンストラクタ」と「プロトタイプ」に分けます。 これらの概念は一緒に使用することを意図していますが、別々に使用することができます。
  • Javascriptは非常に可鍛性の言語であり、人々はそれを別々に使用し、 "継承"とは何かを定義することはできません。
  • 多くの場合、正しいもののサブセットを実行することで逃げることができ、あなたのケースでうまくいくように見えるたくさんの例(このSOの質問に対するいくつかの他の回答を含む)を見つけるでしょう。

Node.jsのEventEmitterの特定のケースについては、ここで動作します:

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);

可能な弱点:

  • util.inheritsを使用するかどうかにかかわらず、サブクラス(Master.prototype)のプロトタイプを設定し、クラスのインスタンス用にスーパーコンストラクター( EventEmitter )をEventEmitterないと、それらは正しく初期化されません。
  • スーパーコンストラクタを呼び出してもプロトタイプを設定しないと、EventEmitterメソッドはあなたのオブジェクトでは動作しません
  • スーパークラス( new EventEmitter )の初期化されたインスタンスをnew EventEmitterとしてMaster.prototypeすると、サブクラスコンストラクターがスーパーコンストラクターEventEmitter呼び出すのではEventEmitter 、 スーパークラスのコンストラクタの動作に応じて、しばらくの間うまく動作しているように見えますが、同じことではありません(EventEmitterでは機能しません)。
  • Object.createを介してオブジェクトの追加レイヤーを追加する代わりに、スーパープロトタイプを直接使用することもできます( Master.prototype = EventEmitter.prototype )。 これは、誰かがあなたのオブジェクトMasterをモンキーEventEmitter 、誤ってMonkeypatchedしたEventEmitterとその他のすべての子孫がうまくいくまでうまくいっているように思えるかもしれません。 それぞれの "クラス"は独自のプロトタイプを持つ必要があります。

再び:EventEmitter(または実際には既存のオブジェクト "class")から継承するには、スーパーコンストラクタにチェーンするコンストラクタを定義し、スーパープロトタイプから派生したプロトタイプを提供します。





eventemitter