In the code for the Express module for Node.js I came across this line, setting inheritance for the server:
Server.prototype.__proto__ = connect.HTTPServer.prototype;
I'm not sure what this does - the MDC docs (https://developer.mozilla.org/en/JavaScript/Guide/Inheritance_Revisited#prototype_and_proto) seem to say that I could just do:
Server.prototype = connect.HTTPServer.prototype;
Indeed, I did this test:
var parent = function(){}
parent.prototype = {
test: function(){console.log('test')};
}
var child1 = function(){};
child1.prototype = parent.prototype;
var instance1 = new child1();
instance1.test(); // 'test'
var child2 = function(){};
child2.prototype.__proto__ = parent.prototype;
var instance2 = new child2();
instance2.test(); // 'test'
Looks to be the same? So yah, I'm wondering what setting object.prototype.__proto is for. Thanks!
Have a look at the diagram on this page (mckoss.com) that shows the prototype
, constructor
, __proto__
relations for a small hierarchy. Also the code below the diagram describes the relation quite well.
When you have a function Base
, and set the prototype of the function object defined, the statement Derived.prototype = new Base;
sets the __proto__
(actually the internal [[prototype]]
) of Derived.prototype
to Base.prototype
automatically, making Derived itself a class that you can instantiate objects from. This seems the be a more standards compliant way of defining a derived class.
From what I read, __proto__
is a non-standard way of accessing the internal [[prototype]]
of an object. It seems to be well supported, but I am not sure if it should be trusted.
In any case, your example Server.prototype.__proto__ = connect.HTTPServer.prototype;
seems to do the derivation the other way around: first define an object, Server
by defining the constructor and the proto, and then hook up the internal [[prototype]]
manually to morph it into a class derived from HTTPServer
.
As for your suggested alternative, Server.prototype = connect.HTTPServer.prototype;
: that is a bad idea. Here, you are setting the prototype of Server
to be the same object as the prototype of HTTPServer
. So any changes you make to Server
class will be directly reflected in HTTPServer
, and will be accessible from other derived classes of HTTPServer
. You can imageine the chaos if two classes derived from HTTPServer
try to define the same member.
The non-standard property __proto__
lets you set the prototype of an existing object.
In your example, both version will achieve the same effect, but there is a difference:
child1
's prototype is the same as parent
's prototype, whereas child2
's prototype is an empty object and this empty object's prototype is the same as parent
's prototype.
Of course as child2
and its prototype don't have a method test
, this method will be looked up further up in the prototype chain.
Also consider this:
You want to create only one object that should inherit from another object. Now, you could write a constructor function, but JavaScript has object literal notation to create objects directly and you want to use it.
If you have a constructor function, letting the new objects inherit from another object is as easy a setting the prototype
of the constructor function to that object.
Obviously this does not work for object literals. But in Firefox you can use __proto__
to set it:
var server = {
__proto__: connect.HTTPServer.prototype,
other: properties
};
As this property is not standard, you should avoid using it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With