I've been poking into some Node.js modules in the hopes of learning something I could have missed while creating a module with similar functionality. Then I came across this code from Hound:
function Hound() {
//why this?
events.EventEmitter.call(this)
}
//ok, so inheriting the EventEmitter
util.inherits(Hound, events.EventEmitter);
I know that the util.inherits()
function from Node.js creates a new Parent instance as the prototype of the child constructor as stated in the docs:
The prototype of constructor will be set to a new object created from superConstructor.
So if our constructor is inheriting EventEmitter
through util.inherits()
, what is that code in the constructor for?
It's just making your Hound
class an EventEmitter
object.
It gives your the EventEmitter instance methods to the class.
E.g., houndInstance.emit('something')
Other objects that are listening to these events can then respond to them.
Per your comment:
// constructor
function Hound() {
// equivalent of calling a "super" or "parent" constructor
SomeClass.call(this);
}
In JavaScript, .call(context)
is a means of invoking a function in a specific context. In the example above, we're just calling the SomeClass
constructor and passing this
(the Hound
class in this example) as the context.
From your comments:
But doesn't util.inherits() already cover that? Or am I missing something?
What you are missing is that util.inherits()
merely inherits the parent object. It doesn't set up the constructor to automatically call the parent object's constructor. In most cases it would be enough since most objects don't do much initialization in their constructors.
But events.EventEmitter
apparently does some initialization in the constructor that has some important side effects. Since prototypical inheritance does not automatically call the parent's constructor you need to call it manually in this case. Hence the events.EventEmitter.call(this)
line.
Note that an alternative is to use the module pattern which always calls the parent's constructor. That is because the module pattern is not inheritance per-se but emulates inheritance by abusing the mixin/decorator pattern - it creates an object from the parent constructor and manually add attributes to it. Lots of people don't like the module pattern because it duplicates functions and attrubutes - hence they see it as wasting memory. Also, it's not proper inheritance and so breaks stuff like instanceof
.