Javascript中的无限原型继承

时间:2014-04-17 23:35:07

标签: javascript prototypal-inheritance

我正在学习Javascript中的原型继承,并且据我所知,我正在尝试使用它将进程发送到无限递归链接。

我对原型继承的想法是一个对象(它是一个函数)保存原型链接。该对象的任何实例都指向它。因此,如果我说instance.someproperty,它会查看父对象的原型链。

假设这样,如果我只是将函数原型列表指向自身,当对象试图访问某些属性时它应该进入无限循环。

 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.

我想知道为什么这不起作用,我怎么能让它进入无限循环。

2 个答案:

答案 0 :(得分:5)

使用更常见的风格:

function P(){};
P.prototype = P;

在ECMA-262中,internal prototype property[[Prototype]]表示。

P.prototype 分配不同的对象不会修改 P [[Prototype]],因此其继承链保持为:

P : P[[Prototype]] -> Function.prototype -> Object.prototype -> null

鉴于 P P.prototype 都指向同一个对象, P 实例的[[prototype]]链是:

p : p[[Prototype]] -> P : P[[Prototype]] -> Function.prototype -> Object.prototype -> null

所以没有无限循环。

如果没有分配给 P.prototype ,那么 p 的原型链就是:

p : p[[Prototype]] -> P.prototype -> Object.prototype -> null

要获得无限循环,您可以在支持它的浏览器中将对象分配给自己的__proto__属性(访问[[Prototype]]的公共方式),但我不确定是好主意,Firefox抛出:

"TypeError: cyclic __proto__ value".

答案 1 :(得分:1)

那么,对你的第一个问题:

var p = function(){};

p.prototype = p;
// I also tried p.prototype = new p();

var q = new p();

在第一个中,当您创建p的实例时,您所做的就是将原型设置为函数p本身,该函数本身就是一个对象(带有lengthprototype等属性。它的实际内部原型是Function.prototype,而原型为Object.prototype

第二个略有不同 - 接近但没有雪茄。当您将new p()分配给p.prototype时,prototype属性尚未设置,因此您只需获取{{1}的原始值} property作为实例的内部原型。


继续你的第二个问题。我实际上并不明白为什么要这样做,因为每个属性都会被自己的实例属性所遮蔽。

即使你被允许(没有浏览器这样做),也没有意义。

考虑一下:

prototype

让我们假设这是有效的,忽略了这会在所有浏览器中引发TypeError的事实(为即将推出的ES6规范的附录B中的浏览器指定)。

如果您要访问该属性var a = { b: 1 }; a.__proto__ = a; ,那么您永远不会进入原型链。

如果你试图访问一个不存在的属性,一个实现(如果它允许这样的事情)可以上升到原型链,递归回到自身,或者认识到永远不会找到该属性并返回undefined

当然,存在涉及多个对象的情况:

b

然而,这是非常愚蠢的,没有实际用途(如果首先允许的话 - 它不是)。