What is Event Emitter Call?

I am learning Node Js. I have encountered a snippet of code in my book that stated as follow:

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

//Custom class
function Foo(){
   EventEmitter.call(this);
}
inherits(Foo, EventEmitter);

Foo.prototype.connect = function(){
    this.emit('connected');
}

var foo = new Foo();
foo.on('connected', function(){
    console.log("connected raised!');
}

foo.connect();

My question is that what is "call" here do? Why does the class Foo inherits from EventEmitter? Does that mean that Foo is a child of Event Emitter? If so whu must it be a child of the EventEmitter? I have found another question in Stackoverflow regarding the call (What does EventEmitter.call() do?) However, I did not understand the answer provided... Thanks

Source of the code: Beginning Node.js by Basarat Ali Syed

Upvotes: 4

Views: 2161

Answers (3)

Townsheriff
Townsheriff

Reputation: 709

When applying:

inherits(Foo, EventEmitter);

Foo's prototype is set to EventEmitter.prototype. So, each instance of Foo will have all the of EventEmitter's methods (e.g on, emit etc.)

When Applying:

EventEmitter.call(this)

within Foo's constructor, it is very similar to calling new EventEmitter(), but instead of creating a new context (variable this), you are passing your Foo's context.

For example, here is the EventEmitter's constructor source:

function EventEmitter() {
   this._events = new Events();
   this._eventsCount = 0;
}

The above class members (this._events & this._eventCount) are necessary for maintaining the private state of the event emitter.
Applying merely inherits(Foo, EventEmitter) will enhance Foo's instances with EventEmitter's methods, however Foo's instances will lack a very basic and crucial initialisation process.

In case a super class has an empty constructor you can skip this step, since it has nothing to assign to this variable. Having said that, this is a bad practice since you have no guarantee over this.

Upvotes: 2

ChevCast
ChevCast

Reputation: 59244

It's the ghetto JS way to do inheritance since the language only really supports prototypal inheritance. There is no official language supported class inheritance like in other languages, but the fact that we can run functions against different contexts has become a pretty standard hack for shoehorning in an inheritance hierarchy where an instance of your class can also be considered an instance of its base class. In other words, in var foo = new Foo(), foo can be said to be both an instance of Foo and an EventEmitter. In other languages you can setup more explicit inheritance that is supported by the language and compiler.

.call is available on all functions and lets you execute the function, but with a different context. this in your Foo class refers to the instance of Foo being created and EventEmitter.call(this); is running the EventEmitter constructor, but using your instance of Foo as the this inside the EventEmitter constructor. This way, anything that the EventEmitter constructor would normally setup on a new instance of pure EventEmitter via var emitter = new EventEmitter();, will now actually be setup on your instance of Foo.

Now, this only solves half the goal of achieving JS pseudo-inheritance. If there is anything on the EventEmitter prototype that we need to be on our Foo prototype, merely calling the EventEmitter constructor on your instance of Foo is not enough. This is why you also have to call util.inherits(Foo, EventEmitter);.

util.inherits just sets the prototype of Foo to a new object that inherits from the prototype of EventEmitter. It also adds the EventEmitter constructor as a .super_ property to your Foo constructor which I believe is a Java convention to make it easy to access the base constructor (the constructor of the class you inherit from). https://github.com/joyent/node/blob/master/lib/util.js#L634-L644

Upvotes: -2

jfriend00
jfriend00

Reputation: 708156

The line of code:

EventEmitter.call(this);

calls the constructor of the object you are inheriting from which allows the EventEmitter code to initialize its portion of this object which is part of the inheritance process in Javascript.

EventEmitter() is the constructor function for the EventEmitter object. Since you need to call that constructor with the same this as your new object, you must use either .call() or .apply() with that constructor in order to cause the correct this to be used. Since there are no arguments you are passing to the constructor, .call() is the simplest way to call it.

You must call the EventEmitter() constructor in order to allow it to properly initialize its portion of the object that was created with new Foo(). When using inheritance in Javascript, multiple separate object definitions are using the same object to store their properties and methods so each much initialize their portion of the object and that initialization is started by calling the constructor of the object that you inherited from.

Here's a good reference on the topic of chaining constructors.


It appears from some of your comments that you don't understand what the point of the inheritance in your code is. That code allows you to create an object type Foo that has your own methods on it, but that object ALSO is an eventEmitter and has all the capabilities of an EventEmitter such that it can trigger events, respond to events, etc... This is called "inheritance" where you inherit the functionality of some other object with your own custom object. To make inheritance work, your code does two things. With the inherits(Foo, EventEmitter); line of code, it inherits the prototype of the other object so that it will have all the same methods available and with EventEmitter.call(this);, it calls the constructor of the inherited object so that object can initialize itself properly.

You may want to read a couple of reference articles on Javascript inheritance:

Introduction to Object-Oriented JavaScript

Inheritance and the prototype chain

Understanding JavaScript Inheritance

What is "inheritance" in Javascript?

Inheritance: Object Oriented Programming

Upvotes: 6

Related Questions