问题
I am looking at this article regarding the node.js events module:
http://www.sitepoint.com/nodejs-events-and-eventemitter/
And in it there is this code:
Door.prototype.__proto__ = events.EventEmitter.prototype;
Which supposedly sets the prototype of the Door object to the prototype of the event.EventEmitter.
I believe I know what is the difference between prototype and proto but this code completely confuses me. So my questions is whether instead of using:
Door.prototype.__proto__ = events.EventEmitter.prototype;
The author of the article did not just use this line of code:
Door.prototype= events.EventEmitter.prototype;
回答1:
This code
Door.prototype.__proto__ = events.EventEmitter.prototype
makes Door.prototype
inherit from events.EventEmitter.prototype
.
So the prototype chain will be like
doorInstance -> Door.prototype -> events.EventEmitter.prototype
This approach is similar to
Door.prototype = Object.create(events.EventEmitter.prototype)
The difference is that modifying the [[Prototype]] does not create a new object, but it has a great negative impact on performance.
Instead, this code
Door.prototype = events.EventEmitter.prototype
makes Door
instances inherit directly from events.EventEmitter.prototype
.
That is, you won't be able to add specific methods in Door.prototype
without polluting events.EventEmitter.prototype
.
回答2:
I did some more research on this and although there are various diagrams on the matter I think this graphic explains it best:
http://www.mollypages.org/misc/js.mp
To summarize:
Door.prototype is only available on the Door type not on the instances of Door.
doorInstance.__proto_ gets set to Door.prototype (points to Door.prototype) when the doorInstance is created view new Door().
Interestingly Door.prototype has a __proto_ property of its own (Door.prototype.__proto_) which points to Object.prototype.
When properties get looked up as part of the Javascript prototypal inheritance the __proto_ property is used on each object in the prototypal chain. We can forget about the prototype property as it is not present on instances. For example doorInstace -> doorInstance.__proto_ -> doorInstance.__proto_.__proto_. So ultimately the last __proto_ to be looked up will be the one pointing to the Object.prototype.
So going back to the question, setting the Door.prototype.__proto_ like this:
Door.prototype.__proto_ = events.EventEmitter.prototype
Will in reality change the Door.prototype.__proto_ to point to the events.EventEmitter.prototype instead of the Object.prototype. In this way properties on the doorInstance will be looked up in the following order: doorInstance -> doorInstance.__proto_ -> doorIntacne.__proto_.__proto (events.EventEmitter.prototype)
In this way doorInstance is essentially inheriting from events.EventEmitter.prototype.
This code:
Door.prototype = events.EventEmitter.prototype;
Will have the same effect because doorInstance.__proto_ points to Door.prototype and setting Door.prototype to events.EventEmitter.prototype will make doorInstance.__proto_ point to events.EventEmitter.prototype. In this way properties on the doorInstance will be looked up in the following order: doorInstance -> doorInstance.__proto_(events.EventEmitter.prototype).
However as already answered by Oriol, because Door.prototype and events.EventEmitter.prototype now point to the same object, changes in either prototype will affect the other prototype, which can result in unexpected behavior.
来源:https://stackoverflow.com/questions/31474864/setting-object-prototype-proto-instead-of-just-object-prototype