How to use instanceof with a class which is not defined in the current context?

Viewed 570

This is going to be a bit tricky but I'll do my best to explain,

Consider the following code:

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]

It's pretty straightforward to see that (class B).b() is going to return an instance of an object of type(/class) A. And we can evaluate this using the instanceof operator [1].

Now, a problem arises when, for whatever reason, we do not have a definition for class A in our current scope. One scenario where such thing may happen, is when you import/require an object from a library and many of its internal classes are not exposed.

Since there is no definition for A, it is not possible to do <symbol> instanceof A ...

So, how may one actually perform this check under such scenario?

PS: I already tried the Object.prototype.toString... trick to not avail.

1 Answers

You could create a function that traverses the prototype chain and returns a list of all the super classes of an object including the class from which the object was instantiated from.

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')}`);

You could also do this using a recursive function

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')}`);

Related