Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get constructor name of object

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?

like image 520
kliukovking Avatar asked Sep 14 '17 11:09

kliukovking


2 Answers

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.

like image 108
T.J. Crowder Avatar answered Oct 07 '22 22:10

T.J. Crowder


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.

like image 24
Estus Flask Avatar answered Oct 08 '22 00:10

Estus Flask