39

Given two classes like so:

function A(name) {
    this.name = name;
}

A.prototype.sayName = function() {
    console.log(this.name);
}

var B = require('some-class');

// B is subclass of A?

Is there a way to programmatically determine if B is a subclass of A?

Edit: In my case, B is a function and B.prototype extends A.prototype. B is not the return of new A(). B instanceof A does not seem to work.

conradkleinespel
  • 6,560
  • 10
  • 51
  • 87

1 Answers1

71

To check if B is a subclass of A (excluding the case where B === A):

B.prototype instanceof A

To check if B is a subclass of A (including the case where B === A):

B.prototype instanceof A || B === A

If you have an instance of B, the second test can be simplified to

b instanceof A // where b is an instance of B
tom
  • 21,844
  • 6
  • 43
  • 36
  • 4
    It seems to me that instantiating `B` is never the right thing to do in a generic setting. You can't know what parameters it expects, what side effects it may have or whether B is even supposed to be instantiated at all (it may be intended as an abstract class). Isn't `B.prototype instanceof A || B === A` enough? – mhelvens May 04 '17 at 17:12
  • @mhelvens: You are right, but `new B()` is shorter. I've updated my answer to make it the second option instead of the first and added a note that it creates an instance of B. – tom May 11 '17 at 15:26
  • Thing is, you can't even be sure it creates an instance of `B`. A constructor can return any value. And 'shorter' is not a very convincing argument. Write a function and use that. :-) – mhelvens May 11 '17 at 19:01
  • you know that we can use `Object.create` right? using `new` is quite anti-pattern! :D – Clite Tailor Oct 10 '18 at 11:53
  • 2
    `new` is not anti-pattern. Many of the industry's top developers use it all the time. – ffxsam Oct 24 '18 at 15:48
  • Also, Promises are natively instantiated via `new Promise`. You're saying native JS classes are anti-pattern. – ffxsam Oct 24 '18 at 16:13
  • 2
    @ffxsam you've misunderstood - using `Object.create(proto)` is a way to create a new object whose prototype is of the specified type, but which does not actually invoke the constructor. It's invoking the constructor and creating an instance when all you want to do is to check the prototype chain that's the anti-pattern. – Alnitak May 22 '19 at 12:50
  • shorter is meaningless, creating a new instance runs code, which may mutate the class's state (or even global state. who knows) which is kinda extremely nasty – somebody Feb 19 '21 at 14:55
  • @somebody I updated my answer and removed `new B() instanceof A`. It was a neat idea ([credit](https://stackoverflow.com/questions/18939192/how-to-test-if-b-is-a-subclass-of-a-in-javascript-node/18939541#comment27966262_18939192)) and can be useful if the programmer already has an instance of B, but as already pointed out in the comments it is not general-purpose and can have unexpected behaviour. I replaced it with `b instanceof A` where `b` is assumed to be an instance of B, glossing over the details of how one might obtain an instance of B. – tom Feb 20 '21 at 11:48