如何将 instanceof 与当前上下文中未定义的类一起使用?

alm*_*now 5 javascript ecmascript-5 ecmascript-6

这会有点棘手,但我会尽力解释,

考虑以下代码:

class A { a() { return true; } }

class B { b() { return new A(); } }

var b = new B();
console.log(b instanceof B);     // true
console.log(b.b() instanceof A); // true <--- [1]

Run Code Online (Sandbox Code Playgroud)

很容易看到它将(class B).b()返回一个 type(/class) 对象的实例A。我们可以使用instanceof运算符来评估它[1]

现在,无论出于何种原因,当我们A在当前范围内没有类的定义时,就会出现问题。可能发生这种情况的一种情况是,当您从库中导入/需要一个对象并且它的许多内部类没有公开时。

由于没有对 的定义A,因此无法执行<symbol> instanceof A...

那么,在这种情况下,如何实际执行此检查?

PS:我已经尝试过 Object.prototype.toString... 技巧无济于事。

You*_*saf 2

您可以创建一个函数来遍历原型链并返回对象的所有超类的列表,包括实例化该对象的类。

class Foo {}
class X extends Foo{}
class A extends X{}

class B { b() { return new A(); } }

function getParents(obj) {
  const arr = [];

  while (obj = Reflect.getPrototypeOf(obj)) {
    arr.push(obj.constructor.name);
  }  
    
  return arr;
}

var b = new B().b();
const parents = getParents(b);

console.log(`b instance of A = ${parents.includes('A')}`);
console.log(`b instance of X = ${parents.includes('X')}`);
console.log(`b instance of Foo = ${parents.includes('Foo')}`);
console.log(`b instance of Object = ${parents.includes('Object')}`);
Run Code Online (Sandbox Code Playgroud)

您也可以使用递归函数来完成此操作

class Foo {}
class X extends Foo{}
class A extends X{}


class B { b() { return new A(); } }

function getParents(obj, arr = null) {
  if (!arr) arr = [];
  
  const protoTypeObj = Reflect.getPrototypeOf(obj);
  if (!protoTypeObj) return;
  
  arr.push(protoTypeObj.constructor.name);
  
  getParents(protoTypeObj, arr);
  
  return arr;
}

var b = new B().b();
const parents = getParents(b);

console.log(`b instance of A = ${parents.includes('A')}`);
console.log(`b instance of X = ${parents.includes('X')}`);
console.log(`b instance of Foo = ${parents.includes('Foo')}`);
console.log(`b instance of Object = ${parents.includes('Object')}`);
Run Code Online (Sandbox Code Playgroud)

  • 当一个简单的循环就足够了时,为什么要让它递归呢?:D (3认同)