Get constructor name of object

11,047

Solution 1

You can get it from name on constructor:

console.log(object.constructor.name);

When you do ex = new Example, for instance, in the normal course of things that makes Example.prototype the prototype of the object that was created (ex), and the object inherits a constructor property from that object that refers back to the constructor (Example).

I say "in the normal course of things" because there are various ways those normal relationships can be changed. For instance, code could have overridden the constructor property with an own property on the object (ex.constructor = somethingElse;). To rule out that specific scenario, you could use:

console.log(Object.getPrototypeOf(object).constructor.name);

Live example:

class Example1 {
}
const e1 = new Example1();
console.log(e1.constructor.name); // "Example1"

class Example2 {
    constructor() {
        this.constructor = "I'm special";
    }
}
const e2 = new Example2();
console.log(Object.getPrototypeOf(e2).constructor.name); // "Example2"

The TC39 committee members that specify JavaScript were happy enough to use the instance's constructor property in Promises when building the new promise that then and catch return (see Step 3 here which goes here and reads constructor from the instance) (and in some other places), so you wouldn't be out on your own if you also used it. They don't even go to the prototype of the instance.

But yes, just for completeness, even if you go to the prototype for it, it's still possible for that to lead you astray, since the prototype's constructor property can also be mucked with:

class Example {
}
Example.prototype.constructor = Object; // Why would anyone do this? People are weird.
const e = new Example();
console.log(Object.getPrototypeOf(e).constructor.name); // "Object"

It's also possible to redefine the name on a function:

class Example {
}
// Why would someone do this? People are weird.
Object.defineProperty(Example, "name", {
    value: "flibberdeegibbit"
});
const e = new Example();
console.log(Object.getPrototypeOf(e).constructor.name); // "flibberdeegibbit"

So...caveat user.


Note that the function name property is new as of ES2015 (as is class syntax). If you're using class syntax via a transpiler, it may or may not set name correctly.

Solution 2

Generally object instanceof Process is desirable if it's known for sure that object originates from this class/function. There may be situations where this won't be so. The appearance of several Process can be caused by iframes, multiple package versions, etc.

There is name property that already exists in regular functions class constructors. A known pitfall is that it will be mangled in minified code, so it is generally useless in browser JS, and its use can be considered an antipattern. name cannot be reassigned (in some browsers), so a separate property is needed to identify the class.

The proper way is to avoid this problem

But I suppose it will be an error if I try to call this method in object which doesn't belong to this class and hasn't got method like this.

is to use a getter:

class Process {
  get className() { return 'Process'; }
  ...
}

Or a property:

class Process {
  ...
}
Process.prototype.className = 'Process';

As a result, there may be several Process classes that have Process className identifier. This may be desirable or not. While instanceof associates class instance with one particular class.

Solution 3

Use .constructor.name on the object. Each object's constructor by default refers to his creation function, which has a name property. It returns the name of the function.

class SomeClass {

}

const obj = new SomeClass();

console.log(obj.constructor.name);
Share:
11,047
kliukovking
Author by

kliukovking

Updated on July 27, 2022

Comments

  • kliukovking
    kliukovking almost 2 years

    How can I get name of object's class? I mean "Process" in this exampleenter image description here

    I see two ways to get it. First one is to write a getter in this class like

     getClassName(){return "Process"}
    

    But I suppose it will be an error if I try to call this method in object which doesn't belong to this class and hasn't got method like this.

    And second one is using object instanceof Process. But maybe there is some way to make it better and more correctly?

  • Bergi
    Bergi over 6 years
    "If you want to be a bit paranoid" …you wouldn't use any .constructor or .name property :-)
  • T.J. Crowder
    T.J. Crowder over 6 years
    @Bergi: Meh, there are degrees of paranoia. :-)
  • kliukovking
    kliukovking over 6 years
    @T.J.Crowder Thank you very much!!
  • Estus Flask
    Estus Flask over 6 years
    To my knowledge, name is readonly in some browsers. The answer doesn't mention that name will be mangled in minified code, which is absolute no-no for using it in client side code.
  • T.J. Crowder
    T.J. Crowder over 6 years
    @estus: name is read-only, but configurable (weird -- in my view -- but true), hence using Object.defineProperty above rather than using .name = ... As for mangled names in minified code, we're now well into the land of speculation, and since the name will still be the name of the function (mangled or otherwise)... (That said: I would have liked to see an answer to bergi's question on the question from the OP as to why they want this info...)
  • Estus Flask
    Estus Flask over 6 years
    It's non-configurable in some V8 versions. Even if legacy Chrome versions are not taken into account, the support in Android browsers is harder to ignore, this will produce nasty bugs that are hard to detect and debug. These are good reasons for me to not recommend name by default - unless the question has node.js tag.
  • T.J. Crowder
    T.J. Crowder over 6 years
    @estus: Just as well I didn't recommend using it then. I answered the question that was asked. I also included a couple of caveats around it.