I've been trying to understand why I see code like this in node all the time:
var util = require("util");
var events = require("events");
function MyStream() {
events.EventEmitter.call(this);
}
util.inherits(MyStream, events.EventEmitter);
MyStream.prototype.write = function(data) {
this.emit("data", data);
}
I went to the documentation in order to better understand.
util.inherits(constructor, superConstructor)
The prototype of constructor will be set to a new object created from superConstructor.
As an additional convenience, superConstructor will be accessible through the constructor.super_ property.
From that I assumed that meant that all util.inherits
does is this:
exports.inherits = function (constructor, superConstructor) {
constructor.super_ = superConstructor;
constructor.prototype = new superConstructor();
}
Seemed to make sense to me, but then I noticed in the MyStream
constructor they invoke event.EventEmitter.call(this);
so that the EventEmitter
constructor runs on the instance of MyStream
being created. I was totally confused by this since constructor.prototype = new superConstructor();
should be all it needed right? Well I went to the source and found the actual function signature.
exports.inherits = function(ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
Once I saw this I got totally confused while trying to figure out what Object.create
is doing here. Why is it doing this instead of just new superCtor()
? I tried looking at the documentation for Object.create
but I'm still confused. Let me try and see if I can articulate what I think is going on and you guys can correct me :)
The first argument to Object.create(proto [, propertiesObject ])
is the prototype that you want this new object to have. I guess this is just easier than the classic method of defining a constructor and setting its prototype
property? The second argument is a simple hash with properties on it that should be added to the newly created object that it will return? So, this...
var myInstance = Object.create(somePrototype, { someProp: someVal, someProp2: someVal2);
...instead of this?
function MyClass () {
this.prop = someVal;
this.prop2 = someVal2;
// etc
}
MyClass.prototype = somePrototype;
var myInstance = new MyClass();
I'm not sure if my understanding of Object.create
is totally accurate so hopefully you guys can clarify. Assuming that I now understand Object.create
why then does the util.inherits
function not look like this?
exports.inherits = function(ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = Object.create(new superCtor, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
To Summarize
Wouldn't the new superCtor
eliminate the need to do events.EventEmitter.call(this)
inside of MyStream
? Why is it so important that we make the prototypes the same and then run the EventEmitter
constructor on the actual instance that MyStream
is creating instead of just having the prototype
be an actual instance of EventEmitter
?
Also, what is the purpose of adding a constructor
property to ctor
's prototype? Is that a JavaScript thing I don't know about?