问题
I'm learning prototypal inheritance in Javascript, and for my understanding I'm trying to use it to send the process into infinite recursive chaining.
My idea of prototypal inheritance is that an object (which is a function) holds prototype link. Any instance of that object points to it. So if I say instance.someproperty it looks into the prototype chain of the parent object.
Assuming this, If I just point function prototype list to itself, it should go into infinite loop when object tries to access some property.
var p = function(){};
p.prototype = p;
// I also tried p.prototype = new p();
var q = new p();
// and now when I say q.something, it should never be able to find it.
I want to know why this doesn't work and how can I make it to go into infinite loop.
回答1:
Using more common style:
function P(){};
P.prototype = P;
In ECMA-262, the internal prototype property is denoted by [[Prototype]]
.
Assigning a different object to P.prototype does not modify P's [[Prototype]]
, so its inheritance chain remains as:
P : P[[Prototype]] -> Function.prototype -> Object.prototype -> null
Given that P and P.prototype both point to the same object, the [[prototype]]
chain of an instance of P is:
p : p[[Prototype]] -> P : P[[Prototype]] -> Function.prototype -> Object.prototype -> null
so no endless loop.
Without the assignment to P.prototype, p's prototype chain would have been:
p : p[[Prototype]] -> P.prototype -> Object.prototype -> null
To get an endless loop, you can assign an object to its own __proto__
property (the public way to access [[Prototype]]
) in those browsers that support it, but I'm not sure that's a good idea, Firefox throws:
"TypeError: cyclic __proto__ value".
回答2:
Well, to your first question:
var p = function(){};
p.prototype = p;
// I also tried p.prototype = new p();
var q = new p();
In the first one, all you're doing when you create an instance of p
is setting the prototype to the function p
itself, which is an object in its own right (with properties such as length
, prototype
, etc.). Its actual internal prototype is Function.prototype
, which in turn has a prototype of Object.prototype
.
The second one is slightly different -- close, but no cigar. When you're assigning new p()
to p.prototype
, the prototype
property has not been set yet, so you're just going to get the original value of the prototype
property as the instance's internal prototype.
Moving on to your second question. I don't actually see why you'd do this, as every property would be shadowed by its own instance property.
Even if you were allowed to (no browsers do), there would be no point.
Consider this:
var a = { b: 1 };
a.__proto__ = a;
Let's assume that this works, ignore the fact that this throws a TypeError in all browsers (which is specified for browsers in Annex B of the upcoming ES6 spec).
If you were to access the property b
, you'd never go up the prototype chain.
If you attempted to access a non-existent property, an implementation (if it allowed for such a thing) could either go up the prototype chain, back to itself recursively, or recognise that the property would never be found and return undefined.
Of course, there is the situation where there are multiple objects involved:
var a = { x: 1 };
var b = { y: 2 };
b.__proto__ = a;
a.__proto__ = b;
However, this is ridiculously stupid and of no practical use (if permitted in the first place -- it isn't).
来源:https://stackoverflow.com/questions/23145203/infinite-prototypal-inheritance-in-javascript