如何检查一个 Javascript 类是否继承了另一个(不创建 obj)

How to check if a Javascript Class inherits another (without creating an obj)?

本文关键字:是否 继承 另一个 obj 创建 一个 何检查 检查 Javascript      更新时间:2023-09-26

例如:

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

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

尝试以下操作:

ChildClass.prototype instanceof ParentClass

您可以使用 测试直接继承

B.prototype.constructor === A

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

B.prototype instanceof A

(这第二种方案首先由涅槃提库给出)

回到

2017:
检查这是否适合您

ParentClass.isPrototypeOf(ChildClass)

如果要防止阴影,可以选择:

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

> 陷阱:请注意,如果您使用多个执行上下文/窗口,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 of 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

它在类 (B) 和类实例 (b) 之间有所不同......

function A(){}
function B(){}
B.prototype = new A();
const b = new B();
console.log(B.prototype instanceof A);
// true
console.log(Object.getPrototypeOf(b) instanceof A);
// true

同样地

class E extends Error {}
const e = new E();
console.log(E.prototype instanceof Error);
// true
console.log(e.constructor.prototype instanceof Error);
// true
console.log(Object.getPrototypeOf(e) instanceof Error);
// true

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

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

其他的都不适合我。ChatGPT也不能。我已经通过以下代码解决了。

/**
 * Checks whether a given object is inherited from a specified superclass.
 * 
 * @param {Object} object - The object to check.
 * @param {Function} superClass - The superclass to compare against.
 * @returns {boolean} - True if the object is a subclass of the superclass, false otherwise.
 */
isInheritedFrom(object, superClass) {
    console.log(`Checking if ${object.constructor.name} is a subclass of ${superClass.name}`);
    
    let currentProto = Object.getPrototypeOf(object.constructor);
    while (currentProto) {
        if (currentProto.name === superClass.name) {
            console.log(`Found match for a superclass of ${object.constructor.name} with ${superClass.name}`);
            // object is a subclass of the superclass
            return true;
        }
        currentProto = Object.getPrototypeOf(currentProto);
    }
    
    console.log(`No match found for ${object.constructor.name} with ${superClass.name}`);
    // object is not a subclass of the superclass
    return false;
}