1123

I created a JavaScript object, but how I can determine the class of that object?

I want something similar to Java's .getClass() method.

6
  • 16
    for example , I make a Person like this : var p = new Person(); I have a Person Object that called "p", how can I use "p" to get back the Class name: "Person". Commented Aug 8, 2009 at 18:20
  • 8
    Duplicate Commented May 6, 2011 at 6:12
  • Update: As of ECMAScript 6, JavaScript still doesn't have a class type. It does have a class keyword and class syntax for creating prototypes in which the methods can more easily access super. Commented Aug 1, 2016 at 3:10
  • What about Object.className? Commented Jan 23, 2017 at 12:04
  • 3
    @Paul-Basenko : "className" won't tell you the object's class, but will return the content of an HTML element's "class" property, which refers to CSS classes. You also want to use "classList" to manage them easily, but it's not related to the OP's question. Commented Mar 4, 2020 at 16:51

24 Answers 24

1459

There's no exact counterpart to Java's getClass() in JavaScript. Mostly that's due to JavaScript being a prototype-based language, as opposed to Java being a class-based one.

Depending on what you need getClass() for, there are several options in JavaScript:

A few examples:

function Foo() {}
var foo = new Foo();

typeof Foo;             // == "function"
typeof foo;             // == "object"

foo instanceof Foo;     // == true
foo.constructor.name;   // == "Foo"
Foo.name                // == "Foo"    

Foo.prototype.isPrototypeOf(foo);   // == true

Foo.prototype.bar = function (x) {return x+x;};
foo.bar(21);            // == 42

Note: if you are compiling your code with Uglify it will change non-global class names. To prevent this, Uglify has a --mangle param that you can set to false is using gulp or grunt.

Sign up to request clarification or add additional context in comments.

11 Comments

That should probably be func.prototype (yes, functions are objects, but the prototype property is only relevant on function objects).
you might also want to mention instanceof/isPrototypeOf() and the non-standard __proto__
ES5 has aditionally Object.getPrototypeOf()
Warning: don't rely on constructor.name if your code is being minified. The function name is going to change arbitrarily.
@igorsantos07, at least in 2019; the top 5-10 google results for "online javascript minifier" recognize construction.name as a token to be ignored / not minimize. Besides most (if not all) minifier software provide exception rules.
|
465
obj.constructor.name

is a reliable method in modern browsers. Function.name was officially added to the standard in ES6, making this a standards-compliant means of getting the class of a JavaScript object as a string. If the object is instantiated with var obj = new MyClass(), it will return "MyClass".

It will return "Number" for numbers, "Array" for arrays and "Function" for functions, etc. It generally behaves as expected. The only cases where it fails are if an object is created without a prototype, via Object.create( null ), or the object was instantiated from an anonymously-defined (unnamed) function.

Also note that if you are minifying your code, it's not safe to compare against hard-coded type strings. For example instead of checking if obj.constructor.name == "MyType", instead check obj.constructor.name == MyType.name. Or just compare the constructors themselves, however this won't work across DOM boundaries as there are different instances of the constructor function on each DOM.

6 Comments

Function.name is not (yet) part of the JavaScript standard. It is currently supported in Chrome and Firefox, but not in IE(10).
Object.create(something).constructor === something.constructor, which is not quite correct too. So obj.constructor is unreliable for all objects made with Object.create, no matter with or without a prototype.
Warning: don't rely on constructor.name if your code is being minified. The function name is going to change arbitrarily.
@adalbertpl It had to do with manually chaining prototypes, before ES6. It's good to know constructor.name behaves as expected with the new class support in ES6.
|
47

This getNativeClass() function returns undefined for undefined values and null for null.
For all other values, the CLASSNAME-part is extracted from [object CLASSNAME], which is the result of using Object.prototype.toString.call(value).

getAnyClass() behaves the same as getNativeClass(), but also supports custom constructors:

function getNativeClass(obj) {
  if (typeof obj === "undefined") return "undefined";
  if (obj === null) return "null";
  return Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
}

function getAnyClass(obj) {
  if (typeof obj === "undefined") return "undefined";
  if (obj === null) return "null";
  return obj.constructor.name;
}

getNativeClass("")   === "String";
getNativeClass(true) === "Boolean";
getNativeClass(0)    === "Number";
getNativeClass([])   === "Array";
getNativeClass({})   === "Object";
getNativeClass(null) === "null";

getAnyClass(new (function Foo(){})) === "Foo";
getAnyClass(new class Foo{}) === "Foo";

// etc...

4 Comments

Object.prototype.getClass = function(){ using 'this' instead of obj would be nice
of course then null and undefined would be uncheckable since only the Object would have the getClass method
This only works on native objects. If you have some kind of inheritance going you will always get "Object".
Yeah, the last line of the function should just be return obj.constructor.name. That gives the same results, plus also handles non native objects.
34

We can read Class's name of an instance by just doing 'instance.constructor.name' like in this example:

class Person {
  type = "developer";
}
let p = new Person();

p.constructor.name // Person

1 Comment

all fun until you minify your JS and your class name is now n JS really blows for this sort of thing.
22

To get the "pseudo class", you can get the constructor function, by

obj.constructor

assuming the constructor is set correctly when you do the inheritance -- which is by something like:

Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;

and these two lines, together with:

var woofie = new Dog()

will make woofie.constructor point to Dog. Note that Dog is a constructor function, and is a Function object. But you can do if (woofie.constructor === Dog) { ... }.

If you want to get the class name as a string, I found the following working well:

http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects

function getObjectClass(obj) {
    if (obj && obj.constructor && obj.constructor.toString) {
        var arr = obj.constructor.toString().match(
            /function\s*(\w+)/);

        if (arr && arr.length == 2) {
            return arr[1];
        }
    }

    return undefined;
}

It gets to the constructor function, converts it to string, and extracts the name of the constructor function.

Note that obj.constructor.name could have worked well, but it is not standard. It is on Chrome and Firefox, but not on IE, including IE 9 or IE 10 RTM.

1 Comment

You get points for woofie.
16

You can get a reference to the constructor function which created the object by using the constructor property:

function MyObject(){
}

var obj = new MyObject();
obj.constructor; // MyObject

If you need to confirm the type of an object at runtime you can use the instanceof operator:

obj instanceof MyObject // true

3 Comments

doesn't it return the constructor function itself, like, you can call it again and create a new object of that type?
@SparK Yes, though you can still use this for a comparison so long as you are on the same DOM (you are comparing function objects). However it is much better practice to turn the constructor into a string and compare that, specifically because it works across DOM boundaries when using iframes.
This answer returns the "class" (or at least a handle the object which can be used to create an instance of the class - which is the same as "the class"). The above answers all returned strings which is not the same as "the class object" (as it were).
13

i had a situation to work generic now and used this:

class Test {
  // your class definition
}

nameByType = function(type){
  return type.prototype["constructor"]["name"];
};

console.log(nameByType(Test));

thats the only way i found to get the class name by type input if you don't have a instance of an object.

(written in ES2017)

dot notation also works fine

console.log(Test.prototype.constructor.name); // returns "Test" 

1 Comment

Ah this is what I was looking for. If it's not instantiated you have to use 'prototype' to get the class name. Thanks a ton!
10

In keeping with its unbroken record of backwards-compatibility, ECMAScript 6, JavaScript still doesn't have a class type (though not everyone understands this). It does have a class keyword as part of its class syntax for creating prototypes—but still no thing called class. JavaScript is not now and has never been a classical OOP language. Speaking of JS in terms of class is only either misleading or a sign of not yet grokking prototypical inheritance (just keeping it real).

That means this.constructor is still a great way to get a reference to the constructor function. And this.constructor.prototype is the way to access the prototype itself. Since this isn't Java, it's not a class. It's the prototype object your instance was instantiated from. Here is an example using the ES6 syntactic sugar for creating a prototype chain:

class Foo {
  get foo () {
    console.info(this.constructor, this.constructor.name)
    return 'foo'
  }
}

class Bar extends Foo {
  get foo () {
    console.info('[THIS]', this.constructor, this.constructor.name, Object.getOwnPropertyNames(this.constructor.prototype))
    console.info('[SUPER]', super.constructor, super.constructor.name, Object.getOwnPropertyNames(super.constructor.prototype))

    return `${super.foo} + bar`
  }
}

const bar = new Bar()
console.dir(bar.foo)

This is what that outputs using babel-node:

> $ babel-node ./foo.js                                                                                                                   ⬡ 6.2.0 [±master ●]
[THIS] [Function: Bar] 'Bar' [ 'constructor', 'foo' ]
[SUPER] [Function: Foo] 'Foo' [ 'constructor', 'foo' ]
[Function: Bar] 'Bar'
'foo + bar'

There you have it! In 2016, there's a class keyword in JavaScript, but still no class type. this.constructor is the best way to get the constructor function, this.constructor.prototype the best way to get access to the prototype itself.

Comments

8

Don't use o.constructor because it can be changed by the object content. Instead, use Object.getPrototypeOf()?.constructor.

const fakedArray = JSON.parse('{ "constructor": { "name": "Array" } }');

// returns 'Array', which is faked.
fakedArray.constructor.name;

// returns 'Object' as expected
Object.getPrototypeOf(fakedArray)?.constructor?.name;

Comments

6

For Javascript Classes in ES6 you can use object.constructor. In the example class below the getClass() method returns the ES6 class as you would expect:

var Cat = class {

    meow() {

        console.log("meow!");

    }

    getClass() {

        return this.constructor;

    }

}

var fluffy = new Cat();

...

var AlsoCat = fluffy.getClass();
var ruffles = new AlsoCat();

ruffles.meow();    // "meow!"

If you instantiate the class from the getClass method make sure you wrap it in brackets e.g. ruffles = new ( fluffy.getClass() )( args... );

Comments

5

If you need to not only GET class but also EXTEND it from having just an instance, write:

let's have

 class A{ 
   constructor(name){ 
     this.name = name
   }
 };

 const a1 = new A('hello a1');

so to extend A having the instance only use:

const a2 = new (Object.getPrototypeOf(a1)).constructor('hello from a2')
// the analog of const a2 = new A()

console.log(a2.name)//'hello from a2'

Comments

4

getClass() function using constructor.prototype.name

I found a way to access the class that is much cleaner than some of the solutions above; here it is.

function getClass(obj) {

   // if the type is not an object return the type
   if((let type = typeof obj) !== 'object') return type; 
    
   //otherwise, access the class using obj.constructor.name
   else return obj.constructor.name;   
}

How it works

the constructor has a property called name accessing that will give you the class name.

cleaner version of the code:

function getClass(obj) {

   // if the type is not an object return the type
   let type = typeof obj
   if((type !== 'object')) { 
      return type; 
   } else { //otherwise, access the class using obj.constructor.name
      return obj.constructor.name; 
   }   
}

1 Comment

A comment from above: "Warning: don't rely on constructor.name if your code is being minified. The function name is going to change arbitrarily."
2

In javascript, there are no classes, but I think that you want the constructor name and obj.constructor.toString() will tell you what you need.

2 Comments

This will return the entire definition of the constructor function as a string. What you really want is .name.
but .name is not defined even on IE 9
2

I find object.constructor.toString() return [object objectClass] in IE ,rather than function objectClass () {} returned in chome. So,I think the code in http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects may not work well in IE.And I fixed the code as follows:

code:

var getObjectClass = function (obj) {
        if (obj && obj.constructor && obj.constructor.toString()) {
            
                /*
                 *  for browsers which have name property in the constructor
                 *  of the object,such as chrome 
                 */
                if(obj.constructor.name) {
                    return obj.constructor.name;
                }
                var str = obj.constructor.toString();
                /*
                 * executed if the return of object.constructor.toString() is 
                 * "[object objectClass]"
                 */
                 
                if(str.charAt(0) == '[')
                {
                        var arr = str.match(/\[\w+\s*(\w+)\]/);
                } else {
                        /*
                         * executed if the return of object.constructor.toString() is 
                         * "function objectClass () {}"
                         * for IE Firefox
                         */
                        var arr = str.match(/function\s*(\w+)/);
                }
                if (arr && arr.length == 2) {
                            return arr[1];
                        }
          }
          return undefined; 
    };
    

Comments

1

Agree with dfa, that's why i consider the prototye as the class when no named class found

Here is an upgraded function of the one posted by Eli Grey, to match my way of mind

function what(obj){
    if(typeof(obj)==="undefined")return "undefined";
    if(obj===null)return "Null";
    var res = Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
    if(res==="Object"){
        res = obj.constructor.name;
        if(typeof(res)!='string' || res.length==0){
            if(obj instanceof jQuery)return "jQuery";// jQuery build stranges Objects
            if(obj instanceof Array)return "Array";// Array prototype is very sneaky
            return "Object";
        }
    }
    return res;
}

Comments

1

Here's a implementation of getClass() and getInstance()

You are able to get a reference for an Object's class using this.constructor.

From an instance context:

function A() {
  this.getClass = function() {
    return this.constructor;
  }

  this.getNewInstance = function() {
    return new this.constructor;
  }
}

var a = new A();
console.log(a.getClass());  //  function A { // etc... }

// you can even:
var b = new (a.getClass());
console.log(b instanceof A); // true
var c = a.getNewInstance();
console.log(c instanceof A); // true

From static context:

function A() {};

A.getClass = function() {
  return this;
}

A.getInstance() {
  return new this;
}

2 Comments

Why not just this.constructor?
I don't know, but if it is better, you can definitely edit the answer to improve it as you find better, after all this is a community.
1

You can also do something like this

 class Hello {
     constructor(){
     }
    }
    
      function isClass (func) {
        return typeof func === 'function' && /^class\s/.test(Function.prototype.toString.call(func))
    }
    
   console.log(isClass(Hello))

This will tell you if the input is class or not

1 Comment

The above isClass implementation fails for e.g. isClass(Array), isClass(Object), ... Besides that, the OP didn't want to know whether a function is a class constructor but instead wants to get/access the class (which is the constructor function) reference of any given type.
0

I suggest using Object.prototype.constructor.name:

Object.defineProperty(Object.prototype, "getClass", {
    value: function() {
      return this.constructor.name;
    }
});

var x = new DOMParser();
console.log(x.getClass()); // `DOMParser'

var y = new Error("");
console.log(y.getClass()); // `Error'

Comments

0

Regarding the OP's concern:

I created a JavaScript object, but how can I determine the class of that object?

For a reliable and trustworthy type-detection approach within custom type systems - whether based on ES3-style constructor functions or ES6 classes - there have been robust solutions available for years (looking back as of this writing). These solutions revolve around the two most commonly recommended techniques in this thread:

Ensuring Reliable Type Detection

  • The well-known symbol Symbol.toStringTag provides a safe way to define a custom type representation for objects. This approach has been dependable for custom type systems since around 2017/2018.

  • Constructor names (obj.constructor.name) are unreliable when code undergoes minification, as function and class names may be replaced or removed during deployment. However, reliability can be ensured by explicitly assigning a durable name to any constructor function of interest.

Implementing Safe Type Detection

A helper function - e.g., applyDurableTypeDetection - can automate this process. It takes two arguments:

  1. The constructor function.
  2. The custom type's name (string).

The key mechanism enabling both toStringTag calls and constructor-name overrides is Object.defineProperty, configured in its strictest form (non-enumerable, non-configurable/non-writable).

To ensure a constructor’s name remains fixed, one does apply:

Object.defineProperty(constructor, 'name', {
  configurable: false,
  value: typeName,
});

For toStringTag, however, a getter function is required. The type name must either be preserved within a closure or bound to a utility function, such as:

Object.defineProperty(constructor.prototype, Symbol.toStringTag, {
  get: exposeBoundValue.bind(null, typeName),
});

// declared outside the function scope of `applyDurableTypeDetection`.
function exposeBoundValue(value) {
  return value;
}

Verification via Test Cases

The following example code demonstrates and validates these techniques in action:

// type-detection test for values/instances of the built-in `String` type.

const stringValue = '';
const stringType = new String;

// spoofing attempt ... successful.
stringType[Symbol.toStringTag] = 'COMPROMISED';

console.log({
  about: 'ALMOST RELIABLE string value/type detection.',

  type_signature_of_string_value: exposeTypeSignature(stringValue),
  constructor_name_of_string_value: getConstructorName(stringValue),

  type_signature_of_string_type: exposeTypeSignature(stringType),
  constructor_name_of_string_type: getConstructorName(stringType),
});


// partly unreliable type-detection for e.g. a custom `DSLError` error type.

class aa/* name substitution due to code minification */ extends Error {
  constructor(...args) {
    super(...args);
  }
  get [Symbol.toStringTag]() {
    return 'DSLError';
  }
}
const customError = new aa;

// spoofing attempt ... NOT successful.
customError[Symbol.toStringTag] = 'FOO';

console.log({
  about: 'NOT THAT RELIABLE detection of a custom error type.',

  // taken care of via the *well-known symbol* `Symbol.toStringTag`.
  type_signature_of_custom_error: exposeTypeSignature(customError),

  // not trustable due to function name substitutions through minification. 
  constructor_name_of_custom_error: getConstructorName(customError),
});


// apply durable detection of custom types like the above custom error type.

class bb/* name substitution due to code minification */ extends Error {
  constructor(...args) {
    super(...args);
  }
}
applyDurableTypeDetection(bb, 'DSLError');

const anotherCustomError = new bb;

// spoofing attempt ... NOT successful.
anotherCustomError[Symbol.toStringTag] = 'BAR';

console.log({
  about: 'durable/reliable detection of a custom error type.',

  type_signature_of_custom_error: exposeTypeSignature(anotherCustomError),
  constructor_name_of_custom_error: getConstructorName(anotherCustomError),
});


// it is possible to even patch a reliable detection of built-in types.

applyDurableTypeDetection(String, 'String');

const anotherStringValue = '';
const anotherStringType = new String;

// spoofing attempt ... NOT successful.
stringType[Symbol.toStringTag] = 'COMPROMISED';

console.log({
  about: 'reliable (patched) detection, even of built-in types.',

  type_signature_of_string_value: exposeTypeSignature(anotherStringValue),
  constructor_name_of_string_value: getConstructorName(anotherStringValue),

  type_signature_of_string_type: exposeTypeSignature(anotherStringType),
  constructor_name_of_string_type: getConstructorName(anotherStringType),
});
.as-console-wrapper { bottom: auto; right: auto; top: 0; min-height: 100%; }
<script>
function exposeTypeSignature(value) {
  return Object.prototype.toString.call(value);
}

function getConstructor(value) {
  return Object.getOwnPropertyDescriptor(
    Object.getPrototypeOf(value),
    'constructor',
  ).value;
}
function getConstructorName(value) {
  return getConstructor(value).name;
}


function isFunction(value) {
  return (
    typeof value === 'function' &&
    typeof value.call === 'function' &&
    typeof value.apply === 'function'
  );
}
function isString(value) {
  return exposeTypeSignature(value) === '[object String]';
  // return getConstructorName(value) === 'String';
}


function exposeBoundValue(value) {
  return value;
}
function applyDurableTypeDetection(constructor, typeName) {
  // guard
  if (!isFunction(constructor)) {
    throw new TypeError(
      'The provided "constructor" parameter has to be a function type.'
    );
  }
  // guard
  if (!isString(typeName)) {
    throw new TypeError(
      'The provided "typeName" parameter needs to be a string.'
    );
  }
  Object.defineProperty(constructor, 'name', {
    configurable: false,
    value: typeName,
  });
  Object.defineProperty(constructor.prototype, Symbol.toStringTag, {
    get: exposeBoundValue.bind(null, typeName),
  });
  return constructor;
}
</script>

1 Comment

Whoever decided to negatively reward the above provided fail-save type-detection/type-hardening approach as well as the extensive effort of explaining it in detail, has not the slightest clue about the matter of assuring a reliable type-detection across javascript realms/domains.
-1

If you have access to an instance of the class Foo (say foo = new Foo()) then there is exactly one way to get access to the the class from the instance: foo.Contructor in Javascript = foo.getClass() in Java.

eval() is another way, but since eval() is never recommended and works for everything (analogous to Java reflection), that answer is not recommended. foo.Constructor = Foo

1 Comment

it looks like your answer got truncated. Please check and extend the answer or fix the last phrase.
-2

Javascript is a class-less languages: there are no classes that defines the behaviour of a class statically as in Java. JavaScript uses prototypes instead of classes for defining object properties, including methods, and inheritance. It is possible to simulate many class-based features with prototypes in JavaScript.

1 Comment

Update: As of ECMAScript 6, JavaScript still doesn't have a class type. It does have a class keyword and class syntax for creating prototypes in which the methods can more easily access super.
-4

Question seems already answered but the OP wants to access the class of and object, just like we do in Java and the selected answer is not enough (imho).

With the following explanation, we can get a class of an object(it's actually called prototype in javascript).

var arr = new Array('red', 'green', 'blue');
var arr2 = new Array('white', 'black', 'orange');

You can add a property like this:

Object.defineProperty(arr,'last', {
  get: function(){
    return this[this.length -1];
  }
});
console.log(arr.last) // blue

But .last property will only be available to 'arr' object which is instantiated from Array prototype. So, in order to have the .last property to be available for all objects instantiated from Array prototype, we have to define the .last property for Array prototype:

Object.defineProperty(Array.prototype,'last', {
  get: function(){
    return this[this.length -1];
  }
});
console.log(arr.last) // blue
console.log(arr2.last) // orange

The problem here is, you have to know which object type (prototype) the 'arr' and 'arr2' variables belongs to! In other words, if you don't know class type (prototype) of the 'arr' object, then you won't be able to define a property for them. In the above example, we know arr is instance of the Array object, that's why we used Array.prototype to define a property for Array. But what if we didn't know the class(prototype) of the 'arr'?

Object.defineProperty(arr.__proto__,'last2', {
  get: function(){
    return this[this.length -1];
  }
});
console.log(arr.last) // blue
console.log(arr2.last) // orange

As you can see, without knowing that 'arr' is an Array, we can add a new property just bu referring the class of the 'arr' by using 'arr.__proto__'.

We accessed the prototype of the 'arr' without knowing that it's an instance of Array and I think that's what OP asked.

1 Comment

The __proto__ property is deprecated, and has almost no advantage over the prototype property.
-4

There is one another technique to identify your class You can store ref to your class in instance like below.

class MyClass {
    static myStaticProperty = 'default';
    constructor() {
        this.__class__ = new.target;
        this.showStaticProperty = function() {
            console.log(this.__class__.myStaticProperty);
        }
    }
}

class MyChildClass extends MyClass {
    static myStaticProperty = 'custom';
}

let myClass = new MyClass();
let child = new MyChildClass();

myClass.showStaticProperty(); // default
child.showStaticProperty(); // custom

myClass.__class__ === MyClass; // true
child.__class__ === MyClass; // false
child.__class__ === MyChildClass; // true

Comments

-4

class ICT{
   //your logic
}

const student= new ICT();

if (student instanceof ICT) {
  console.log('student is an instance of ICT');
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.