かなりの数のNode.jsライブラリでこのパターンが見られます。
Master.prototype.__proto__ = EventEmitter.prototype;
(ソース ここ )
誰かが例を挙げて私に説明してもらえますか、なぜこれがこのような一般的なパターンであり、いつ便利なのですか?
そのコードの上のコメントにあるように、Master
は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);
これらはドキュメントから直接来ていますが、探している人のためにこの人気のある質問に追加するのはいいことだと思いました。
_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()
を呼び出さないため、this
が未定義になります。こちらをご覧ください issue 。
別のJavascriptオブジェクト、特にNode.jsのEventEmitterから継承するが、実際には一般的なオブジェクトから継承するには、2つのことを行う必要があります。
[[proto]]
として使用されるプロトタイプオブジェクトを提供します。他のオブジェクトから継承している場合、おそらく他のオブジェクトのインスタンスをプロトタイプとして使用する必要があります。これは、他の言語で見られるよりもJavascriptでは複雑です
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
)を呼び出さないと、 t適切に初期化されます。Master
がスーパーコンストラクターEventEmitter
を呼び出す代わりに、new EventEmitter
としてスーパークラスの初期化されたインスタンス(Master.prototype
)を使用しようとする場合があります。スーパークラスコンストラクターの動作によっては、しばらくは正常に動作しているように見えるかもしれませんが、同じことではありません(そして、EventEmitterでは動作しません)。Master.prototype = EventEmitter.prototype
)を直接使用しようとするかもしれません。これは、誰かがあなたのオブジェクトMaster
にモンキーパッチを適用し、誤ってモンキーパッチを適用EventEmitter
および他のすべての子孫にパッチを適用するまで、正常に動作しているように見えるかもしれません。各「クラス」には独自のプロトタイプが必要です。繰り返しになりますが、EventEmitter(または実際に既存のオブジェクト「クラス」)を継承するには、スーパーコンストラクターにチェーンし、スーパープロトタイプから派生したプロトタイプを提供するコンストラクターを定義します。
これは、JavaScriptでプロトタイプ(プロトタイプ?)継承が行われる方法です。 [〜#〜] mdn [〜#〜] から:
オブジェクトまたはnullの可能性があるオブジェクトのプロトタイプを参照します(通常、オブジェクトはObject.prototypeであり、プロトタイプがないことを意味します)。プロトタイプ継承ベースのプロパティルックアップの実装に使用されることがあります。
これも機能します:
var Emitter = function(obj) {
this.obj = obj;
}
// DON'T Emitter.prototype = new require('events').EventEmitter();
Emitter.prototype = Object.create(require('events').EventEmitter.prototype);
JavaScript OOPを理解する は、最近読んだECMAScript 5のOOPで最高の記事の1つです。
http://www.bennadel.com/blog/2187-Extending-EventEmitter-To-Create-An-Evented-Cache-In-Node-js.htm からこのアプローチを考えました:
function EventedObject(){
// Super constructor
EventEmitter.call( this );
return( this );
}
ダグラス・クロックフォードには興味深い継承パターンもいくつかあります。 http://www.crockford.com/javascript/inheritance.html
JavaScriptとNode.jsでは、継承はあまり必要ありません。しかし、継承がスケーラビリティに影響を与える可能性のあるアプリを作成する際には、パフォーマンスを保守性と比較検討します。そうでなければ、どのパターンが全体的な設計の改善につながり、保守性が高く、エラーが発生しにくいかを判断するだけです。
Google Chrome(V8)を使用してjsPerfでさまざまなパターンをテストして、大まかな比較を行います。V8はNode.jsとChromeの両方で使用されるJavaScriptエンジンです。
始めるためのjsPerfsを次に示します。
http://jsperf.com/prototypes-vs-functions/4
Wprlの応答に追加します。彼は「プロトタイプ」の部分を見逃した。
function EventedObject(){
// Super constructor
EventEmitter.call(this);
return this;
}
EventObject.prototype = new EventEmitter(); //<-- you're missing this part