In the dynamic world of JavaScript development, understanding and interacting with object types at runtime is a frequent necessity. Whether you’re debugging, implementing logging, or building highly flexible architectures, knowing the specific class an object belongs to can be incredibly powerful. Modern ES6 classes, while syntactical sugar over JavaScript’s prototype-based inheritance, still represent distinct blueprints for creating objects. This article delves into the most effective and common methods to get the class name of an ES6 class instance, exploring both straightforward approaches and the nuances that arise in complex production environments. Mastering these techniques ensures your applications are more robust, maintainable, and easier to debug, providing clarity when inspecting an object’s origin.
The Primary Method: Leveraging instance.constructor.name
The most direct and widely used method to retrieve the class name of an ES6 class instance is by accessing its constructor.name property. Every object instance in JavaScript has a constructor property, which points to the constructor function (or class) that created it. The name property of a function (including a class constructor) returns the string name by which the function was declared. This combination makes it incredibly straightforward to identify the class of an instance at runtime.
For example, if you have a class named Animal and you create an instance of it, myAnimal, then myAnimal.constructor.name will reliably return the string “Animal”. This simplicity makes it a go-to solution for many common use cases, such as logging object types, conditionally executing code based on an instance’s class, or even dynamic UI rendering. It’s particularly useful during development and debugging phases where original class names are preserved, offering immediate insight into an object’s lineage.
To get the class name of an ES6 class instance, simply access the name property of its constructor. For any instance myInstance, the expression myInstance.constructor.name will return a string representing the name of the class from which myInstance was created. This property directly exposes the class’s declared identifier, making it an efficient and readable way to perform runtime type identification.
class Car { constructor(make, model) { this.make = make; this.model = model; } } const myCar = new Car('Toyota', 'Camry'); console.log(myCar.constructor.name); // Outputs: "Car" class ElectricCar extends Car { constructor(make, model, range) { super(make, model); this.range = range; } } const tesla = new ElectricCar('Tesla', 'Model 3', 300); console.log(tesla.constructor.name); // Outputs: "ElectricCar"
This method works because the JavaScript engine automatically assigns the class name to the name property of the constructor function. It’s a fundamental aspect of how JavaScript handles functions and classes, providing a consistent way to introspect their identities. For more in-depth information on the Function.prototype.name property, you can consult the official MDN Web Docs.
Navigating Nuances: When constructor.name Falls Short
While instance.constructor.name is powerful, it’s not without its limitations, especially in production environments or with certain JavaScript constructs. Understanding these nuances is crucial for building robust applications that behave predictably across different deployment stages.
One of the most significant challenges comes from code minification and obfuscation. Tools like Terser or UglifyJS, commonly used in production builds to reduce file size, often rename class and function names to shorter, single-letter identifiers (e.g., Car becomes a). In such scenarios, myCar.constructor.name might return “a” instead of “Car”, rendering it useless for meaningful identification. This is a critical consideration for any application targeting a production environment, as it directly impacts debugging and runtime logic dependent on class names.
Another area where constructor.name can be misleading is with anonymous classes or functions. If you define a class without a name, like class {}, its constructor.name property will typically return an empty string or “Function” depending on the JavaScript engine and context. Similarly, if you dynamically create classes or use certain advanced patterns (e.g., classes returned from factory functions without explicit names), you might encounter unexpected results. Proxy objects and Question & Answer :
Are there any ‘harmonious’ ways to get the class name from ES6 class instance? Other than
someClassInstance.constructor.name
Currently I’m counting on Traceur implementation. And it seems that Babel has a polyfill for Function.name while Traceur doesn’t.
To sum it all up: there was no other way in ES6/ES2015/Harmony, and nothing is expected ATM in ES.Next.
It may provide useful patterns for unminified server-side applications but is unwanted in applications meant for browser/desktop/mobile.
Babel uses core-js to polyfill Function.name, it should be loaded manually for Traceur and TypeScript applications as appropriate.
someClassInstance.constructor.name is exactly the correct way to do this. Transpilers may not support this, but it is the standard way per the specification. (The name property of functions declared via ClassDeclaration productions is set in 14.5.15, step 6.)