【问题标题】:How to check if a Javascript Class inherits another (without creating an obj)?如何检查 Javascript 类是否继承了另一个(不创建 obj)?
【发布时间】:2013-01-07 07:26:09
【问题描述】:

例如:

function A(){}
function B(){}
B.prototype = new A();

如何检查B类是否继承A类?

【问题讨论】:

    标签: javascript class inheritance


    【解决方案1】:

    尝试以下方法:

    ChildClass.prototype instanceof ParentClass
    

    【讨论】:

    • ES6 class 怎么样? class A extends B{} 那么我该如何检查类A的继承情况@
    • @Omid ES6 类语法 主要就是这样:一些特殊的语法。在幕后,“类”的实际处理没有改变,因此您仍然可以使用 A.prototype ... developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
    【解决方案2】:

    你可以测试直接继承

    B.prototype.constructor === A
    

    要测试间接继承,您可以使用:

    B.prototype instanceof A
    

    (这第二个解决方案首先由 Nirvana Tikku 给出)

    【讨论】:

    • 不,那只会检查父类,而不是所有的继承链。
    • 刚刚恢复。感谢dystroy(也更新了这个答案)
    【解决方案3】:

    回到 2017 年:
    检查这是否适合你

    ParentClass.isPrototypeOf(ChildClass)
    

    如果您想要防止阴影的替代方案:

    const isPrototypeOf = Function.call.bind(Object.prototype.isPrototypeOf);
    
    // Usage:
    isPrototypeOf(ParentClass, ChildClass); // true or false
    

    【讨论】:

    • 工作完美,但 lint 抱怨。似乎如果程序不能完全控制 ParentClass,那么 ParentClass 就有可能伪造答案。它扩展到所有原型功能。如果程序确实可以完全控制 ParentClass,那么应该没问题。
    • 它如何伪造答案?通过使用符号?以及他们为什么要这样做,如果这可能是设计使然
    • “此外,对象的属性可能会影响 Object.prototype 上的内置函数,这可能会导致意外行为或拒绝服务安全漏洞。”
    • "例如,Web 服务器解析来自客户端的 JSON 输入并直接在结果对象上调用 hasOwnProperty 是不安全的,因为恶意客户端可以发送像 {"hasOwnProperty" 之类的 JSON 值: 1} 并导致服务器崩溃。为避免此类细微错误,最好始终从 Object.prototype 调用这些方法。例如,应将 foo.hasOwnProperty("bar") 替换为 Object.prototype.hasOwnProperty.call (富,“酒吧”)。” -- eslint.org/docs/rules/no-prototype-builtins
    • 我不同意它必须总是被替换。只有在这种情况下,程序员不控制可能的 ParentClass 值的范围时才需要。
    【解决方案4】:

    陷阱:请注意,如果您使用多个执行上下文/窗口,instanceof 将无法按预期工作。见§§


    另外,根据https://johnresig.com/blog/objectgetprototypeof/,这是与instanceof 相同的替代实现:

    function f(_, C) { // instanceof Polyfill
      while (_ != null) {
        if (_ == C.prototype)
          return true;
        _ = _.__proto__;
      }
      return false;
    }
    

    修改它以直接检查类给我们:

    function f(ChildClass, ParentClass) {
      _ = ChildClass.prototype;
      while (_ != null) {
        if (_ == C.prototype)
          return true;
        _ = _.__proto__;
      }
      return false;
    }
    


    旁注

    instanceof 本身会检查 obj.proto 是否为 f.prototype,因此:

    function A(){};
    A.prototype = Array.prototype;
    []instanceof Array // true
    

    和:

    function A(){}
    _ = new A();
    // then change prototype:
    A.prototype = [];
    /*false:*/ _ instanceof A
    // then change back:
    A.prototype = _.__proto__
    _ instanceof A //true
    

    和:

    function A(){}; function B(){};
    B.prototype=Object.prototype;
    /*true:*/ new A()instanceof B 
    

    如果不相等,则在检查中将 proto 与 proto 的 proto 交换,然后将 proto 的 proto 的 proto 交换,以此类推。因此:

    function A(){}; _ = new A()
    _.__proto__.__proto__ = Array.prototype
    g instanceof Array //true
    

    和:

    function A(){}
    A.prototype.__proto__ = Array.prototype
    g instanceof Array //true
    

    和:

    f=()=>{};
    f.prototype=Element.prototype
    document.documentElement instanceof f //true
    document.documentElement.__proto__.__proto__=[];
    document.documentElement instanceof f //false
    

    【讨论】:

    【解决方案5】:

    我认为 Simon 在他的问题中不是指 B.prototype = new A(),因为这肯定不是在 JavaScript 中链接原型的方式。

    假设 B 扩展 A,使用 Object.prototype.isPrototypeOf.call(A.prototype, B.prototype)

    【讨论】:

    • 我想你今天有最好的答案,但至少在 ES6 中引入 class 之前,B.prototype = new A() 确实是链接原型的有效方式(对于那些想要经典风格继承的人)。
    猜你喜欢
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 2012-02-07
    • 2020-04-12
    • 2020-08-27
    • 2012-05-29
    相关资源
    最近更新 更多