Chev Chev - 4 months ago 16
Node.js Question

How should you inherit from EventEmitter in node?

I was reading over this small article to understand inheriting from

EventEmitter
, but I'm a little confused.

He does this:

function Door() {
events.EventEmitter.call(this);
this.open = function() {
this.emit('open');
};
}
Door.prototype.__proto__ = events.EventEmitter.prototype;


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

Why does he manually invoke the EventEmitter constructor with his own constructor's
this
? Also, why does he set the prototype of his contsructor's prototype to the prototype of
EventEmitter
? That's super confusing to me.

Then someone in the comments suggested he do this instead, which seemed more elegant:

function Door() {
events.EventEmitter.call(this);
this.open = function () {
this.emit('open');
}
}
util.inherits(Door, events.EventEmitter);


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

This seems WAY cleaner than the other way, though that's probably just because I fail to understand what's going on in the first instance. I would not be surprised if
util.inherits
is doing the same thing as the first example.

The second one at least makes a little sense to me, but I still don't understand why they don't just do this:

function Door() {
this.open = function () {
this.emit('open');
}
}
Door.prototype = new events.EventEmitter();


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

Can anyone explain to me what the differences between all of these approaches is and why in the first two they invoke
.call(this)
on the
EventEmitter
constructor? I omitted that line while trying out the examples and they still worked.

Answer

The third example is not generally correct: that creates one single EventEmitter instance for all door instances.

Let's imagine a simple case:

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

Suppose we want to create a Bar constructor that inherits from Foo and adds some new properties. If you follow your final example:

var Bar = function() {
    this.something = 5;
}
Bar.prototype = new Foo();

This is wrong because all Bar instance will have the same id property. Instead, we must call the parent constructor for each instance:

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

Note that the final line here is the same as Bar.prototype.__proto__ = Foo.prototype; because Object.create creates a new object whose __proto__ is set to the Object.create argument.