Question

I have been following Hands-On Node.js by by Manuel Teixiera and I stumbled upon this weird behaviour while going through the Event Emitter chapter.

The code suggested by the author consists of something like this:

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

var MyClass = function() {};
util.inherits(MyClass, EventEmitter);
var instance = new MyClass();
instance.on("custom", function() {
   console.log("Holo");
});

instance.emit("custom");*/

Which outputs "Holo" just fine. However, I have also read documentation and SO questions on the subject of how using new Function(); is an anti-pattern that flies in the face of javascript's intended use of prototypical inheritance. This article by David Walsh illustrates the difference between forcing classical inheritance on js and using its capabilities for prototypical inheritance.

So, I tried modify my code by re-writing it like so:

var EventEmitter = require("events").EventEmitter;
var clock = {};
util.inherits(clock, EventEmitter);
clock.on("custom", function(){
    console.log("Holo");
});
clock.emit("custom");

I get an error saying TypeError: Object object has no method 'on'. I don't understand why is this, since I have created the clock object with the util.inherit() helper. The same code using var clock = Object.create(EventEmitter) doesn't work either.

The only instance where I can get the code to work is this:

var EventEmitter = require("events").EventEmitter;
var util = require("util");
var clock = {};
util.inherits(clock, EventEmitter);
clock.prototype.on("custom", function(){
    console.log("Holo");
});
clock.emit = function(){
        clock.prototype.emit("custom");
}
clock.emit();

This outputs "Holo" just fine. The thing is, i don't understand why do I need to access the prototype to set an Event Listener or emit an Event when, supposedly, I made the clock variable delegate it's methods to the EventEmitter object, so they should work fine without the prototype notation.

Would you please help me?

Was it helpful?

Solution

According to the node.js docs:

util.inherits(constructor, superConstructor)

Inherit the prototype methods from one constructor into another. The prototype of constructor will be set to a new object created from superConstructor.

You are passing in an object where util.inherits was designed to expect a constructor. util.inherits operates by redefining the constructor's prototype property, which has prototype chain implications for instances constructed by that constructor. Instead of a constructor function, you have passed in an object, which has its prototype property altered. This has no implications for anyting: you've just created a property on the object called "prototype", which is exactly as special as if you'd made a property on the object called foobar.

There is a school of thought that eschews use of new (in favor of factory functions that call Object.create -- see discussion on Is JavaScript's "new" keyword considered harmful?), but evidently the API designers who implemented util.inherits do not share that view.

Your attempted Object.create(EventEmitter) is indeed not correct, however, because Object.create expects a prototype object, not a constructor function. Instead, you'd do Object.create(EventEmitter.prototype). This is the same as calling new EventEmitter(), except that the Object.create variant does not call the EventEmitter constructor function.

OTHER TIPS

I don't know the implementation of Node's inherit until, but I imagine it simply adds members to the first operand's prototype from the second. It therefore assumes it will be passed a constructor. But passing an empty object will not throw an exception.

You will need to pass a constructor function and call it with new. This is normal and absolutely fine.

Also, where did you get the idea that using new and prototypes were somehow mutually exclusive, or that New is to be avoided? It sounds like you might want to practice your JavaScript OOP a little more.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top