你应该如何继承节点中的EventEmitter?

Che*_*hev 9 javascript events constructor prototype node.js

我正在阅读这篇小文章,以了解继承EventEmitter,但我有点困惑.

他这样做:

function Door() {
    events.EventEmitter.call(this);
    this.open = function() {
        this.emit('open');
    };
}
Door.prototype.__proto__ = events.EventEmitter.prototype;
Run Code Online (Sandbox Code Playgroud)

https://gist.github.com/chevex/7646362

为什么他用自己的构造函数手动调用EventEmitter构造函数this?另外,为什么他将他的contsructor原型的原型设置为原型EventEmitter?这让我感到非常困惑.

然后评论中有人建议他这样做,这似乎更优雅:

function Door() {
    events.EventEmitter.call(this);
    this.open = function () {
      this.emit('open');
    }
}
util.inherits(Door, events.EventEmitter);
Run Code Online (Sandbox Code Playgroud)

https://gist.github.com/chevex/7646447

这看起来比其他方式干净,但这可能只是因为我无法理解第一次发生的事情.如果util.inherits与第一个例子做同样的事情,我不会感到惊讶.

第二个至少对我有点意义,但我仍然不明白他们为什么不这样做:

function Door() {
    this.open = function () {
      this.emit('open');
    }
}
Door.prototype = new events.EventEmitter();
Run Code Online (Sandbox Code Playgroud)

https://gist.github.com/chevex/7646524

任何人都可以向我解释所有这些方法之间的区别是什么以及为什么在前两个方法中它们会.call(this)EventEmitter构造函数上调用?我在尝试示例时省略了这一行,但仍然有效.

aps*_*ers 9

第三个示例通常正确:EventEmitter所有门实例创建一个单一实例.

让我们想象一个简单的案例:

var Foo = function() {
    // each Foo instance has a unique id
    this.id = Math.random();
}
Foo.prototype.doFoo = function() { console.log("Foo!"); }
Run Code Online (Sandbox Code Playgroud)

假设我们想要创建一个Bar继承自Foo并添加一些新属性的构造函数.如果你按照你的最后一个例子:

var Bar = function() {
    this.something = 5;
}
Bar.prototype = new Foo();
Run Code Online (Sandbox Code Playgroud)

这是错误的,因为所有Bar实例都具有相同的id属性.相反,我们必须为每个实例调用父构造函数:

var Bar = function() {
    Foo.call(this);  // set unique `id` on `this`
    this.something = 5;
}
Bar.prototype = Object.create(Foo.prototype);
Run Code Online (Sandbox Code Playgroud)

请注意,此处的最后一行与Bar.prototype.__proto__ = Foo.prototype;因为Object.create创建一个__proto__设置为Object.create参数的新对象相同.