【问题标题】:Infinite prototypal inheritance in JavascriptJavascript 中的无限原型继承
【发布时间】:2014-04-17 23:35:07
【问题描述】:

我正在学习 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.

我想知道为什么这不起作用以及如何让它进入无限循环。

【问题讨论】:

  • 原型函数本身与属性查找无关。
  • 用于学习目的?你在生活中所做的一切对你有用吗?
  • @jfriend 不做黑客也没关系。但我不会因为有这种倾向而抨击人们。
  • @jfriend00 - 通过“黑客”,我将继续更经典的定义,即对事物采取斧头以了解其工作方式的人。 Prototype 更像是一种代理查找机制,而不是真正的继承机制。当它出现时,理解它在我的日常使用/实施中发挥了关键作用。这不是要破坏东西,而是要理解为什么它不会破坏。
  • 我想他问了你为什么要让鸡过马路,而真正的问题是“天哪!它是怎么跑到另一边的?”

标签: javascript prototypal-inheritance


【解决方案1】:

使用更常见的样式:

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

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

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

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

鉴于 PP.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".

【讨论】:

【解决方案2】:

好吧,关于你的第一个问题:

var p = function(){};

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

var q = new p();

在第一个中,当您创建 p 的实例时,您所做的只是将原型设置为函数 p 本身,它本身就是一个对象(具有诸如 length 之类的属性、prototype 等)。它的实际内部原型是Function.prototype,而其原型又是Object.prototype

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


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

即使您被允许(没有浏览器允许),也没有任何意义。

考虑一下:

var a = { b: 1 };
a.__proto__ = a;

让我们假设这可行,忽略这会在所有浏览器中引发 TypeError 的事实(即将到来的 ES6 规范的附件 B 中为浏览器指定了该错误)。

如果您要访问属性 b,您将永远不会上原型链。

如果您尝试访问不存在的属性,则实现(如果它允许这样的事情)可以沿着原型链向上,递归返回自身,或者识别出永远找不到该属性并返回 undefined .

当然还有涉及多个对象的情况:

var a = { x: 1 };
var b = { y: 2 };
b.__proto__ = a;
a.__proto__ = b;

然而,这非常愚蠢而且没有实际用处(如果一开始就允许的话——它是不允许的)。

【讨论】:

    猜你喜欢
    • 2021-01-27
    • 2010-09-28
    • 2010-09-28
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多