40

I would like to get the parent class name (Parent), but I'm only able to retrieve the child class name with this code (Child)...

'use strict';

class Parent {

}

class Child extends Parent {

}

var instance = new Child();
console.log(instance.constructor.name);

Is it possible ?

Thanks !

ceving
  • 21,900
  • 13
  • 104
  • 178
Swadon
  • 422
  • 1
  • 4
  • 7
  • Forgot to say it before, but I don't believe this is possible. In your example, you could check if `instance` is an instance of `Parent` with `instanceof`. What you could do is have your own extends method that store the inheritance tree on each newly created object, but I'm not sure of another way to do it. – Maverick Jul 27 '15 at 11:00
  • @Maverick I will try to do it as you said, thanks anyway for answer ! – Swadon Jul 27 '15 at 11:03
  • no problem :). I'll do some more research because I'm curious myself, but I don't expect to find an elegant solution. If I do find anything, I'll post back here. – Maverick Jul 27 '15 at 11:04
  • @Maverick Great ! :) – Swadon Jul 27 '15 at 11:05

5 Answers5

65

ES6 classes inherit from each other. So when instance.constructor refers to the Child, then you can use Object.getPrototypeOf(instance.constructor) to get the Parent, and then access .name:

Object.getPrototypeOf(instance.constructor).name // == "Parent"

Of course, full ES6 compliance and non-minified code are necessary for this to work. You should never rely on function names in code.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Came here to post this :). You can also go further up the tree if, for example, `c` extends `b` extends `a` :). Also, good news, there is a (very basic) ES6 fiddle: http://www.es6fiddle.net/ – Maverick Jul 30 '15 at 02:42
  • 6
    Be careful using `name` when your code is uglified. – Resist Design Nov 03 '16 at 03:52
  • @rpatel I never meant to endorse the use of a comparison operator here in any way, the OP asked for how to *access* the name. Your approach on comparing names is still prone to be affected by minification, if the minifier does use the same name for distinct classes in different scopes. If you had to compare something, just compare the class references directly. – Bergi Sep 19 '20 at 15:13
  • You're right, if a comparison is needed, comparing the class references directly is the correct way to go. Here's what I should have written: `Object.getPrototypeOf(instance.constructor) === Parent;` – rpatel Sep 19 '20 at 16:51
  • Just to note as well, this will not work with prototypal inheritance. – Michael May 26 '23 at 21:48
  • @Michael It does make use of prototypal inheritance. I think you mean that it does not work with ES5-style constructors where only the prototype objects inherit from each other (and you did not use `Object.setPrototype` on the constructor objects, which also means static methods are not inherited). If your "get parent class name" needs to support that, use `Object.getPrototypeOf(instance.constructor.prototype).constructor.name` or `Object.getPrototypeOf(Object.getPrototypeOf(instance)).constructor.name`, [assuming the `.constructor` is correct](https://stackoverflow.com/q/8453887/1048572). – Bergi May 26 '23 at 22:06
7

Here is something amusing:

class J {}
    
class K extends J {}

class L extends K {}

function getBaseClass(targetClass){
  if(targetClass instanceof Function){
    let baseClass = targetClass;

    while (baseClass){
      const newBaseClass = Object.getPrototypeOf(baseClass);

      if(newBaseClass && newBaseClass !== Object && newBaseClass.name){
        baseClass = newBaseClass;
      }else{
        break;
      }
    }

    return baseClass;
  }
}

console.log(getBaseClass(L)); // Will return J.
Yairopro
  • 9,084
  • 6
  • 44
  • 51
Resist Design
  • 4,462
  • 3
  • 22
  • 35
  • nice, but whats the point of the while.. to get the last copy of that instace? – 1-14x0r Dec 07 '19 at 00:37
  • @1-14x0r It is necessary, if you want to mix-in a class, which inherits something from a base class. – ceving Dec 22 '20 at 19:41
  • 2
    Your answer inspired me to write an [`ancestors` function](https://gist.github.com/ceving/2fa45caa47858ff7c639147542d71f9f). – ceving Dec 22 '20 at 20:27
6

You could technically do

// instanceProto === Child.prototype
var instanceProto = Object.getPrototypeOf(instance);

// parentProto === Parent.prototype
var parentProto = Object.getPrototypeOf(instanceProto);
console.log(parentProto.constructor.name);

keep in mind that these names may all be mangled by minifiers.

mvermand
  • 5,829
  • 7
  • 48
  • 74
loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • You have excluded any step of getting from the child to the parent? I'm confused as to how this answers the question (if it does)? – Maverick Jul 27 '15 at 04:04
  • Thanks for the answer but as @Maverick said, I still need the parent class name to access to the same information... Also, Node.js project, so minification is not a problem – Swadon Jul 27 '15 at 09:15
  • Blah, just a typo. The second line was meant to be `instanceProto`. – loganfsmyth Jul 27 '15 at 16:07
  • Oh sorry ! Thanks for your answer then ! – Swadon Jul 27 '15 at 16:56
2

From proto property:

Child['__proto__'].name

example here: https://stackblitz.com/edit/typescript-s5brk9

Dariusz Filipiak
  • 2,858
  • 5
  • 28
  • 39
1

An alternative and simple solution:

class Foo {}

class Bar extends Foo{}

Object.getPrototypeOf(Bar) === Foo // true

Bar.__proto__ === Foo // true

console.log(Bar.__proto__.name) // Foo
Maxwell s.c
  • 1,583
  • 15
  • 29