20

给定以下代码:

function a() {}
function b() {}
b.prototype = new a();
var b1 = new b();

我们可以留下a已添加到b的原型链中。伟大的。并且,以下所有内容都是正确的:

b1 instanceof b
b1 instanceof a
b1 instanceof Object

我的问题是,如果我们不b1提前知道起源怎么办?我们如何发现其原型链的成员?理想情况下,我想要一个类似[b, a, Object]or的数组["b", "a", "Object"]

这可能吗?我相信我已经在 SO 的某个地方看到了一个答案,该答案描述了如何找出这一点,但我终生无法再次找到它。

4

4 回答 4

7

好吧,对象之间的原型链接 ( [[Prototype]]) 是内部的,一些实现,如 Mozilla,将其公开为obj.__proto__.

ECMAScript 第 5 版的Object.getPrototypeOf方法正是您所需要的,但目前大多数 JavaScript 引擎还没有实现它。

看看 John Resig 的这个实现,它有一个陷阱,它依赖于constructor不支持的引擎的属性__proto__

if ( typeof Object.getPrototypeOf !== "function" ) {
  if ( typeof "test".__proto__ === "object" ) {
    Object.getPrototypeOf = function(object){
      return object.__proto__;
    };
  } else {
    Object.getPrototypeOf = function(object){
      // May break if the constructor has been tampered with
      return object.constructor.prototype;
    };
  }
}

请记住,这不是 100% 可靠的,因为该constructor属性在任何对象上都是可变的。

于 2010-02-11T05:51:16.637 回答
3

编辑——这个答案来自 2010 年,已经过时了。从那时起,该语言添加了Object.getPrototypeOf()API,大大简化了流程。


您可以使用对象的“构造函数”属性在那里找到原型,然后沿着它链接直到到达彩虹的尽头。

function getPrototypes(o) {
  return (function gp(o, protos) {
    var c = o.constructor;
    if (c.prototype) {
      protos.push(c.prototype);
      return gp(c.prototype, protos);
    }
    return protos;
  })(o, []);
}

(也许)(或者也许不是:-)给我一秒钟)(废话;我认为这是可能的,但忽略该代码)

[编辑] 哇,这让我大吃一惊——这个功能很接近但不太正确;建立一系列原型很奇怪,我感到害怕和孤独。我建议只关注上面很棒的@CMS。

于 2010-02-11T05:43:49.167 回答
0

另一种获取原型链的方法:

function getPrototypeChain(obj) {
  let prototypeChain = [];
  (function innerRecursiveFunction(obj) {
    let currentPrototype = (obj != null) ? Object.getPrototypeOf(obj) : null;
    prototypeChain.push(currentPrototype);
    if (currentPrototype != null) {
      innerRecursiveFunction(currentPrototype);
    }
  })(obj);
  return prototypeChain;
}
于 2021-07-10T00:19:09.810 回答
0

这是一个没有递归函数调用的简单方法

function getProtoChain(o) {
    const ans = []
    let t = o
    while (t) {
        t = t.__proto__
        ans.push(t)
    }
    return ans
}

这是此功能的示例使用

class A {}
class B extends A {}
class C extends B {}

console.log(getProtoChain(new C())) // [C: {}, B: {}, A: {}, {}, null]
于 2021-11-23T23:51:05.670 回答