Get the name of an object's type
Asked Answered
R

21

1334

Is there a JavaScript equivalent of Java's class.getName()?

Roice answered 1/12, 2008 at 22:6 Comment(3)
@user34660 I think we can safely assume that what it does is gets the name of an object's type.Welldressed
@StackUnderflow: Except, it actually doesn't. It gets the name of an object's class, which is not the same as an object's type.Remillard
@JörgWMittag Ah yes, of course. Ya see what happens when you go around safely assuming things?Welldressed
F
1689

Is there a JavaScript equivalent of Java's class.getName()?

No.

ES2015 Update: the name of class Foo {} is Foo.name. The name of thing's class, regardless of thing's type, is thing.constructor.name. Builtin constructors in an ES2015 environment have the correct name property; for instance (2).constructor.name is "Number".


But here are various hacks that all fall down in one way or another:

Here is a hack that will do what you need - be aware that it modifies the Object's prototype, something people frown upon (usually for good reason)

Object.prototype.getName = function() { 
   var funcNameRegex = /function (.{1,})\(/;
   var results = (funcNameRegex).exec((this).constructor.toString());
   return (results && results.length > 1) ? results[1] : "";
};

Now, all of your objects will have the function, getName(), that will return the name of the constructor as a string. I have tested this in FF3 and IE7, I can't speak for other implementations.

If you don't want to do that, here is a discussion on the various ways of determining types in JavaScript...


I recently updated this to be a bit more exhaustive, though it is hardly that. Corrections welcome...

Using the constructor property...

Every object has a value for its constructor property, but depending on how that object was constructed as well as what you want to do with that value, it may or may not be useful.

Generally speaking, you can use the constructor property to test the type of the object like so:

var myArray = [1,2,3];
(myArray.constructor == Array); // true

So, that works well enough for most needs. That said...

Caveats

Will not work AT ALL in many cases

This pattern, though broken, is quite common:

function Thingy() {
}
Thingy.prototype = {
    method1: function() {
    },
    method2: function() {
    }
};

Objects constructed via new Thingy will have a constructor property that points to Object, not Thingy. So we fall right at the outset; you simply cannot trust constructor in a codebase that you don't control.

Multiple Inheritance

An example where it isn't as obvious is using multiple inheritance:

function a() { this.foo = 1;}
function b() { this.bar = 2; }
b.prototype = new a(); // b inherits from a

Things now don't work as you might expect them to:

var f = new b(); // instantiate a new object with the b constructor
(f.constructor == b); // false
(f.constructor == a); // true

So, you might get unexpected results if the object your testing has a different object set as its prototype. There are ways around this outside the scope of this discussion.

There are other uses for the constructor property, some of them interesting, others not so much; for now we will not delve into those uses since it isn't relevant to this discussion.

Will not work cross-frame and cross-window

Using .constructor for type checking will break when you want to check the type of objects coming from different window objects, say that of an iframe or a popup window. This is because there's a different version of each core type constructor in each `window', i.e.

iframe.contentWindow.Array === Array // false

Using the instanceof operator...

The instanceof operator is a clean way of testing object type as well, but has its own potential issues, just like the constructor property.

var myArray = [1,2,3];
(myArray instanceof Array); // true
(myArray instanceof Object); // true

But instanceof fails to work for literal values (because literals are not Objects)

3 instanceof Number // false
'abc' instanceof String // false
true instanceof Boolean // false

The literals need to be wrapped in an Object in order for instanceof to work, for example

new Number(3) instanceof Number // true

The .constructor check works fine for literals because the . method invocation implicitly wraps the literals in their respective object type

3..constructor === Number // true
'abc'.constructor === String // true
true.constructor === Boolean // true

Why two dots for the 3? Because Javascript interprets the first dot as a decimal point ;)

Will not work cross-frame and cross-window

instanceof also will not work across different windows, for the same reason as the constructor property check.


Using the name property of the constructor property...

Does not work AT ALL in many cases

Again, see above; it's quite common for constructor to be utterly and completely wrong and useless.

Does NOT work in <IE9

Using myObjectInstance.constructor.name will give you a string containing the name of the constructor function used, but is subject to the caveats about the constructor property that were mentioned earlier.

For IE9 and above, you can monkey-patch in support:

if (Function.prototype.name === undefined && Object.defineProperty !== undefined) {
    Object.defineProperty(Function.prototype, 'name', {
        get: function() {
            var funcNameRegex = /function\s+([^\s(]+)\s*\(/;
            var results = (funcNameRegex).exec((this).toString());
            return (results && results.length > 1) ? results[1] : "";
        },
        set: function(value) {}
    });
}

Updated version from the article in question. This was added 3 months after the article was published, this is the recommended version to use by the article's author Matthew Scharley. This change was inspired by comments pointing out potential pitfalls in the previous code.

if (Function.prototype.name === undefined && Object.defineProperty !== undefined) {
    Object.defineProperty(Function.prototype, 'name', {
        get: function() {
            var funcNameRegex = /function\s([^(]{1,})\(/;
            var results = (funcNameRegex).exec((this).toString());
            return (results && results.length > 1) ? results[1].trim() : "";
        },
        set: function(value) {}
    });
}

Using Object.prototype.toString

It turns out, as this post details, you can use Object.prototype.toString - the low level and generic implementation of toString - to get the type for all built-in types

Object.prototype.toString.call('abc') // [object String]
Object.prototype.toString.call(/abc/) // [object RegExp]
Object.prototype.toString.call([1,2,3]) // [object Array]

One could write a short helper function such as

function type(obj){
    return Object.prototype.toString.call(obj).slice(8, -1);
}

to remove the cruft and get at just the type name

type('abc') // String

However, it will return Object for all user-defined types.


Caveats for all...

All of these are subject to one potential problem, and that is the question of how the object in question was constructed. Here are various ways of building objects and the values that the different methods of type checking will return:

// using a named function:
function Foo() { this.a = 1; }
var obj = new Foo();
(obj instanceof Object);          // true
(obj instanceof Foo);             // true
(obj.constructor == Foo);         // true
(obj.constructor.name == "Foo");  // true

// let's add some prototypical inheritance
function Bar() { this.b = 2; }
Foo.prototype = new Bar();
obj = new Foo();
(obj instanceof Object);          // true
(obj instanceof Foo);             // true
(obj.constructor == Foo);         // false
(obj.constructor.name == "Foo");  // false


// using an anonymous function:
obj = new (function() { this.a = 1; })();
(obj instanceof Object);              // true
(obj.constructor == obj.constructor); // true
(obj.constructor.name == "");         // true


// using an anonymous function assigned to a variable
var Foo = function() { this.a = 1; };
obj = new Foo();
(obj instanceof Object);      // true
(obj instanceof Foo);         // true
(obj.constructor == Foo);     // true
(obj.constructor.name == ""); // true


// using object literal syntax
obj = { foo : 1 };
(obj instanceof Object);            // true
(obj.constructor == Object);        // true
(obj.constructor.name == "Object"); // true

While not all permutations are present in this set of examples, hopefully there are enough to provide you with an idea about how messy things might get depending on your needs. Don't assume anything, if you don't understand exactly what you are after, you may end up with code breaking where you don't expect it to because of a lack of grokking the subtleties.

NOTE:

Discussion of the typeof operator may appear to be a glaring omission, but it really isn't useful in helping to identify whether an object is a given type, since it is very simplistic. Understanding where typeof is useful is important, but I don't currently feel that it is terribly relevant to this discussion. My mind is open to change though. :)

Finis answered 1/12, 2008 at 22:6 Comment(2)
Well, I figured I might as well - the point of Stack Overflow is to be a bit like a wiki, and this is much more in line with that intent, I think. Regardless, I just wanted to be somewhat thorough.Finis
It's important to note that any techniques that inspect the object's constructor method (either with .toString() or .name) will fail to work if your Javascript has been minified with a tool like uglify, or the Rails asset pipeline. The minification renames the constructor, so you will end up with incorrect class names like n. If you're in this scenario, you may want to just manually define a className property on your objects and use that instead.Janeljanela
R
156

Jason Bunting's answer gave me enough of a clue to find what I needed:

<<Object instance>>.constructor.name

So, for example, in the following piece of code:

function MyObject() {}
var myInstance = new MyObject();

myInstance.constructor.name would return "MyObject".

Roice answered 1/12, 2008 at 22:21 Comment(4)
For completeness, it might be worth mentioning that using constructor.name only works if you used a named function as the constructor as opposed to an anonymous function assigned to a variable.Adrenaline
For completeness, it might worth mentioning that it doesn't work in IE browsers --- they do not support the "name" attribute on functions.Fregoso
@EugeneLazutkin why not?Prophylactic
@CollinFox because it was 2008 and IE was like 1.25?Fregoso
I
28

A little trick I use:

function Square(){
    this.className = "Square";
    this.corners = 4;
}

var MySquare = new Square();
console.log(MySquare.className); // "Square"
Isabellaisabelle answered 16/6, 2011 at 22:25 Comment(3)
I do not particularly like this. It's more a kind of dirty trick. On the other hand, if you don't have too many constructors, it might work just fine.Lucrecialucretia
@pimvdb: I think it's cleaner than modifying the object's prototype, a la the accepted answer.Isabellaisabelle
@DanielSzabo if a property should have the same value between all instances of a prototype, I definitely prefer just putting it on the prototype -- putting it on each instance is super-redundant and the metadata is missing from the prototype itself. That said, the wisest solution was adopted in ES6: if you have class Square, the name is Square.name / MySquare.constructor.name rather than Square.prototype.name; by putting name on the constructor function it doesn't pollute the prototype or any instance, but is accessible from either.Gurley
E
19

Update

To be precise, I think OP asked for a function that retrieves the constructor name for a particular object. In terms of Javascript, object does not have a type but is a type of and in itself. However, different objects can have different constructors.

Object.prototype.getConstructorName = function () {
   var str = (this.prototype ? this.prototype.constructor : this.constructor).toString();
   var cname = str.match(/function\s(\w*)/)[1];
   var aliases = ["", "anonymous", "Anonymous"];
   return aliases.indexOf(cname) > -1 ? "Function" : cname;
}

new Array().getConstructorName();  // returns "Array"
(function () {})().getConstructorName(); // returns "Function"

 


Note: the below example is deprecated.

A blog post linked by Christian Sciberras contains a good example on how to do it. Namely, by extending the Object prototype:

if (!Object.prototype.getClassName) {
    Object.prototype.getClassName = function () {
        return Object.prototype.toString.call(this).match(/^\[object\s(.*)\]$/)[1];
    }
}

var test = [1,2,3,4,5];

alert(test.getClassName()); // returns Array
Enteric answered 28/8, 2011 at 15:59 Comment(0)
W
14

Using Object.prototype.toString

It turns out, as this post details, you can use Object.prototype.toString - the low level and generic implementation of toString - to get the type for all built-in types

Object.prototype.toString.call('abc') // [object String]
Object.prototype.toString.call(/abc/) // [object RegExp]
Object.prototype.toString.call([1,2,3]) // [object Array]

One could write a short helper function such as

function type(obj){
    return Object.prototype.toString.call(obj]).match(/\s\w+/)[0].trim()
}

return [object String] as String
return [object Number] as Number
return [object Object] as Object
return [object Undefined] as Undefined
return [object Function] as Function
Weingarten answered 24/3, 2012 at 12:26 Comment(1)
You don't need to use regex to parse out the object name. Just use .slice(): Object.prototype.toString.call(obj).slice( 8, -1 );Information
S
14

You should use somevar.constructor.name like a:

    
    const getVariableType = a => a.constructor.name.toLowerCase();

    const d = new Date();
    const res1 = getVariableType(d); // 'date'
    const num = 5;
    const res2 = getVariableType(num); // 'number'
    const fn = () => {};
    const res3 = getVariableType(fn); // 'function'

    console.log(res1); // 'date'
    console.log(res2); // 'number'
    console.log(res3); // 'function'
Sundsvall answered 28/8, 2018 at 21:34 Comment(1)
doesnt work for the child classesMelleta
N
10

Here is a solution that I have come up with that solves the shortcomings of instanceof. It can check an object's types from cross-windows and cross-frames and doesn't have problems with primitive types.

function getType(o) {
    return Object.prototype.toString.call(o).match(/^\[object\s(.*)\]$/)[1];
}
function isInstance(obj, type) {
    var ret = false,
    isTypeAString = getType(type) == "String",
    functionConstructor, i, l, typeArray, context;
    if (!isTypeAString && getType(type) != "Function") {
        throw new TypeError("type argument must be a string or function");
    }
    if (obj !== undefined && obj !== null && obj.constructor) {
        //get the Function constructor
        functionConstructor = obj.constructor;
        while (functionConstructor != functionConstructor.constructor) {
            functionConstructor = functionConstructor.constructor;
        }
        //get the object's window
        context = functionConstructor == Function ? self : functionConstructor("return window")();
        //get the constructor for the type
        if (isTypeAString) {
            //type is a string so we'll build the context (window.Array or window.some.Type)
            for (typeArray = type.split("."), i = 0, l = typeArray.length; i < l && context; i++) {
                context = context[typeArray[i]];
            }
        } else {
            //type is a function so execute the function passing in the object's window
            //the return should be a constructor
            context = type(context);
        }
        //check if the object is an instance of the constructor
        if (context) {
            ret = obj instanceof context;
            if (!ret && (type == "Number" || type == "String" || type == "Boolean")) {
                ret = obj.constructor == context
            }
        }
    }
    return ret;
}

isInstance requires two parameters: an object and a type. The real trick to how it works is that it checks if the object is from the same window and if not gets the object's window.

Examples:

isInstance([], "Array"); //true
isInstance("some string", "String"); //true
isInstance(new Object(), "Object"); //true

function Animal() {}
function Dog() {}
Dog.prototype = new Animal();

isInstance(new Dog(), "Dog"); //true
isInstance(new Dog(), "Animal"); //true
isInstance(new Dog(), "Object"); //true
isInstance(new Animal(), "Dog"); //false

The type argument can also be a callback function which returns a constructor. The callback function will receive one parameter which is the window of the provided object.

Examples:

//"Arguments" type check
var args = (function() {
    return arguments;
}());

isInstance(args, function(w) {
    return w.Function("return arguments.constructor")();
}); //true

//"NodeList" type check
var nl = document.getElementsByTagName("*");

isInstance(nl, function(w) {
    return w.document.getElementsByTagName("bs").constructor;
}); //true

One thing to keep in mind is that IE < 9 does not provide the constructor on all objects so the above test for NodeList would return false and also a isInstance(alert, "Function") would return false.

Noctule answered 5/3, 2012 at 14:42 Comment(0)
I
10

I was actually looking for a similar thing and came across this question. Here is how I get types: jsfiddle

var TypeOf = function ( thing ) {

    var typeOfThing = typeof thing;

    if ( 'object' === typeOfThing ) {

        typeOfThing = Object.prototype.toString.call( thing );

        if ( '[object Object]' === typeOfThing ) {

            if ( thing.constructor.name ) {
                return thing.constructor.name;
            } 

            else if ( '[' === thing.constructor.toString().charAt(0) ) {
                typeOfThing = typeOfThing.substring( 8,typeOfThing.length - 1 );
            } 

            else {

                typeOfThing = thing.constructor.toString().match( /function\s*(\w+)/ );

                if ( typeOfThing ) { 
                    return typeOfThing[1];
                } 

                else {
                    return 'Function';
                }
            }
        } 

        else {
            typeOfThing = typeOfThing.substring( 8,typeOfThing.length - 1 );
        }
    }

    return typeOfThing.charAt(0).toUpperCase() + typeOfThing.slice(1);
}
Irons answered 7/12, 2013 at 13:0 Comment(0)
U
7

Use constructor.name when you can, and regex function when I can't.

Function.prototype.getName = function(){
  if (typeof this.name != 'undefined')
    return this.name;
  else
    return /function (.+)\(/.exec(this.toString())[1];
};
Underachieve answered 12/8, 2011 at 19:38 Comment(0)
B
7

The kind() function from Agave.JS will return:

  • the closest prototype in the inheritance tree
  • for always-primitive types like 'null' and 'undefined', the primitive name.

It works on all JS objects and primitives, regardless of how they were created, and doesn't have any surprises.

var kind = function(item) {
        var getPrototype = function(item) {
            return Object.prototype.toString.call(item).slice(8, -1);
        };
        var kind, Undefined;
        if (item === null ) {
            kind = 'null';
        } else {
            if ( item === Undefined ) {
                kind = 'undefined';
            } else {
                var prototype = getPrototype(item);
                if ( ( prototype === 'Number' ) && isNaN(item) ) {
                    kind = 'NaN';
                } else {
                    kind = prototype;
                }
            }
        }
        return kind;
    };

Examples:

Numbers

kind(37) === 'Number'
kind(3.14) === 'Number'
kind(Math.LN2) === 'Number'
kind(Infinity) === 'Number'
kind(Number(1)) === 'Number'
kind(new Number(1)) === 'Number'

NaN

kind(NaN) === 'NaN'

Strings

kind('') === 'String'
kind('bla') === 'String'
kind(String("abc")) === 'String'
kind(new String("abc")) === 'String'

Booleans

kind(true) === 'Boolean'
kind(false) === 'Boolean'
kind(new Boolean(true)) === 'Boolean'

Arrays

kind([1, 2, 4]) === 'Array'
kind(new Array(1, 2, 3)) === 'Array'

Objects

kind({a:1}) === 'Object'
kind(new Object()) === 'Object'

Dates

kind(new Date()) === 'Date'

Functions

kind(function(){}) === 'Function'
kind(new Function("console.log(arguments)")) === 'Function'
kind(Math.sin) === 'Function'

undefined

kind(undefined) === 'undefined'

null

kind(null) === 'null'
Bats answered 23/10, 2013 at 15:4 Comment(1)
Link is broken. Can you simply show the code of kind()?Ketty
F
7

Here is an implementation based on the accepted answer:

/**
 * Describes the type of a variable.
 */
class VariableType
{
    type;
    name;

    /**
     * Creates a new VariableType.
     *
     * @param {"undefined" | "null" | "boolean" | "number" | "bigint" | "array" | "string" | "symbol" |
     *  "function" | "class" | "object"} type the name of the type
     * @param {null | string} [name = null] the name of the type (the function or class name)
     * @throws {RangeError} if neither <code>type</code> or <code>name</code> are set. If <code>type</code>
     * does not have a name (e.g. "number" or "array") but <code>name</code> is set.
     */
    constructor(type, name = null)
    {
        switch (type)
        {
            case "undefined":
            case "null":
            case "boolean" :
            case "number" :
            case "bigint":
            case "array":
            case "string":
            case "symbol":
                if (name !== null)
                    throw new RangeError(type + " may not have a name");
        }
        this.type = type;
        this.name = name;
    }

    /**
     * @return {string} the string representation of this object
     */
    toString()
    {
        let result;
        switch (this.type)
        {
            case "function":
            case "class":
            {
                result = "a ";
                break;
            }
            case "object":
            {
                result = "an ";
                break;
            }
            default:
                return this.type;
        }
        result += this.type;
        if (this.name !== null)
            result += " named " + this.name;
        return result;
    }
}

const functionNamePattern = /^function\s+([^(]+)?\(/;
const classNamePattern = /^class(\s+[^{]+)?{/;

/**
 * Returns the type information of a value.
 *
 * <ul>
 *   <li>If the input is undefined, returns <code>(type="undefined", name=null)</code>.</li>
 *   <li>If the input is null, returns <code>(type="null", name=null)</code>.</li>
 *   <li>If the input is a primitive boolean, returns <code>(type="boolean", name=null)</code>.</li>
 *   <li>If the input is a primitive number, returns <code>(type="number", name=null)</code>.</li>
 *   <li>If the input is a primitive or wrapper bigint, returns
 *   <code>(type="bigint", name=null)</code>.</li>
 *   <li>If the input is an array, returns <code>(type="array", name=null)</code>.</li>
 *   <li>If the input is a primitive string, returns <code>(type="string", name=null)</code>.</li>
 *   <li>If the input is a primitive symbol, returns <code>(type="symbol", null)</code>.</li>
 *   <li>If the input is a function, returns <code>(type="function", name=the function name)</code>. If the
 *   input is an arrow or anonymous function, its name is <code>null</code>.</li>
 *   <li>If the input is a function, returns <code>(type="function", name=the function name)</code>.</li>
 *   <li>If the input is a class, returns <code>(type="class", name=the name of the class)</code>.
 *   <li>If the input is an object, returns
 *   <code>(type="object", name=the name of the object's class)</code>.
 *   </li>
 * </ul>
 *
 * Please note that built-in types (such as <code>Object</code>, <code>String</code> or <code>Number</code>)
 * may return type <code>function</code> instead of <code>class</code>.
 *
 * @param {object} value a value
 * @return {VariableType} <code>value</code>'s type
 * @see <a href="https://mcmap.net/q/36775/-get-the-name-of-an-object-39-s-type">https://mcmap.net/q/36775/-get-the-name-of-an-object-39-s-type</a>
 * @see isPrimitive
 */
function getTypeInfo(value)
{
    if (value === null)
        return new VariableType("null");
    const typeOfValue = typeof (value);
    const isPrimitive = typeOfValue !== "function" && typeOfValue !== "object";
    if (isPrimitive)
        return new VariableType(typeOfValue);
    const objectToString = Object.prototype.toString.call(value).slice(8, -1);
    // eslint-disable-next-line @typescript-eslint/ban-types
    const valueToString = value.toString();
    if (objectToString === "Function")
    {
        // A function or a constructor
        const indexOfArrow = valueToString.indexOf("=>");
        const indexOfBody = valueToString.indexOf("{");
        if (indexOfArrow !== -1 && (indexOfBody === -1 || indexOfArrow < indexOfBody))
        {
            // Arrow function
            return new VariableType("function");
        }
        // Anonymous and named functions
        const functionName = functionNamePattern.exec(valueToString);
        if (functionName !== null && typeof (functionName[1]) !== "undefined")
        {
            // Found a named function or class constructor
            return new VariableType("function", functionName[1].trim());
        }
        const className = classNamePattern.exec(valueToString);
        if (className !== null && typeof (className[1]) !== "undefined")
        {
            // When running under ES6+
            return new VariableType("class", className[1].trim());
        }
        // Anonymous function
        return new VariableType("function");
    }
    if (objectToString === "Array")
        return new VariableType("array");

    const classInfo = getTypeInfo(value.constructor);
    return new VariableType("object", classInfo.name);
}

   
function UserFunction()
{
}

function UserClass()
{
}

let anonymousFunction = function()
{
};

let arrowFunction = i => i + 1;

console.log("getTypeInfo(undefined): " + getTypeInfo(undefined));
console.log("getTypeInfo(null): " + getTypeInfo(null));
console.log("getTypeInfo(true): " + getTypeInfo(true));
console.log("getTypeInfo(5): " + getTypeInfo(5));
console.log("getTypeInfo(\"text\"): " + getTypeInfo("text"));
console.log("getTypeInfo(userFunction): " + getTypeInfo(UserFunction));
console.log("getTypeInfo(anonymousFunction): " + getTypeInfo(anonymousFunction));
console.log("getTypeInfo(arrowFunction): " + getTypeInfo(arrowFunction));
console.log("getTypeInfo(userObject): " + getTypeInfo(new UserClass()));
console.log("getTypeInfo(nativeObject): " + getTypeInfo(navigator.mediaDevices.getUserMedia));

We only use the constructor property when we have no other choice.

Felsite answered 4/1, 2017 at 5:55 Comment(2)
getObjectClass regex need a tweak to support class tooEdina
@deadManN I've updated the implementation to support classes. Please note that the function names and their return values might have changed. Give it a try and let me know what you think.Felsite
H
6

You can use the instanceof operator to see if an object is an instance of another, but since there are no classes, you can't get a class name.

Haematogenesis answered 1/12, 2008 at 22:13 Comment(2)
While it's true that JavaScript doesn't have classes as language construct, the generic convention is still that a type of an object is called a class..Enteric
@greg Sure but instanceof just checks whether an object inherits from another objects. Eg, a simple [] inherits from Array, but Array also inherits from Object. Since most objects have multiple levels of inheritance, finding the closest prototype is a better technique. See my answer for how.Bats
Y
3

You can use the "instanceof" operator to determine if an object is an instance of a certain class or not. If you do not know the name of an object's type, you can use its constructor property. The constructor property of objects, is a reference to the function that is used to initialize them. Example:

function Circle (x,y,radius) {
    this._x = x;
    this._y = y;
    this._radius = raduius;
}
var c1 = new Circle(10,20,5);

Now c1.constructor is a reference to the Circle() function. You can alsow use the typeof operator, but the typeof operator shows limited information. One solution is to use the toString() method of the Object global object. For example if you have an object, say myObject, you can use the toString() method of the global Object to determine the type of the class of myObject. Use this:

Object.prototype.toString.apply(myObject);
Yellowhammer answered 2/12, 2008 at 18:52 Comment(0)
Y
3

Say you have var obj;

If you just want the name of obj's type, like "Object", "Array", or "String", you can use this:

Object.prototype.toString.call(obj).split(' ')[1].replace(']', '');
Yonkers answered 2/8, 2017 at 19:35 Comment(0)
M
2

The closest you can get is typeof, but it only returns "object" for any sort of custom type. For those, see Jason Bunting.

Edit, Jason's deleted his post for some reason, so just use Object's constructor property.

Methanol answered 1/12, 2008 at 22:22 Comment(0)
E
1

Fairly Simple!

  • My favorite method to get type of anything in JS
function getType(entity){
    var x = Object.prototype.toString.call(entity)
    return x.split(" ")[1].split(']')[0].toLowerCase()
}
  • my favorite method to check type of anything in JS
function checkType(entity, type){
    return getType(entity) === type
}
Eirene answered 6/5, 2020 at 12:10 Comment(0)
I
1

For of those of you reading this and want a simple solution that works fairly well and has been tested:

const getTypeName = (thing) => {
  const name = typeof thing
  if (name !== 'object') return name
  if (thing instanceof Error) return 'error'
  if (!thing) return 'null'
  return ({}).toString.call(thing).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

To get insight on why this works, checkout the polyfill documentation for Array.isArray(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray#polyfill

Ingroup answered 10/2, 2021 at 7:4 Comment(0)
B
0

If anyone was looking for a solution which is working with jQuery, here is the adjusted wiki code (the original breaks jQuery).

Object.defineProperty(Object.prototype, "getClassName", {
    value: function() {
        var funcNameRegex = /function (.{1,})\(/;
        var results = (funcNameRegex).exec((this).constructor.toString());
        return (results && results.length > 1) ? results[1] : "";
    }
});
Beller answered 29/7, 2014 at 11:49 Comment(1)
Yeah, jQuery fails to do a 'hasOwnProperty' check and so enumerates the getName and falls over.Nebraska
R
0

Lodash has many isMethods so if you're using Lodash maybe a mixin like this can be useful:

  // Mixin for identifying a Javascript Object

  _.mixin({
      'identify' : function(object) {
        var output;
          var isMethods = ['isArguments', 'isArray', 'isArguments', 'isBoolean', 'isDate', 'isArguments', 
              'isElement', 'isError', 'isFunction', 'isNaN', 'isNull', 'isNumber', 
              'isPlainObject', 'isRegExp', 'isString', 'isTypedArray', 'isUndefined', 'isEmpty', 'isObject']

          this.each(isMethods, function (method) {
              if (this[method](object)) {
                output = method;
                return false;
              }
          }.bind(this));
      return output;
      }
  });

It adds a method to lodash called "identify" which works as follow:

console.log(_.identify('hello friend'));       // isString

Plunker: http://plnkr.co/edit/Zdr0KDtQt76Ul3KTEDSN

Radicalism answered 24/9, 2015 at 17:0 Comment(0)
P
0

Ok, folks I've been slowly building a catch all method for this over some years lol! The trick is to:

  1. Have a mechanism for creating classes.
  2. Have a mechanism for checking all user created classes, primitives and values created/generated by native constructors.
  3. Have a mechanism for extending user created classes into new ones so that the above functionality permeates through your code/application/library/etc..

For an example (or to see how I dealt with the problem) look at the following code on github: https://github.com/elycruz/sjljs/blob/master/src/sjl/sjl.js and search for:

classOf =, classOfIs =, and or defineSubClass = (without the backticks (`)).

As you can see I have some mechanisms in place to force classOf to always give me the classes/constructors type name regardless of whether it is a primitive, a user defined class, a value created using a native constructor, Null, NaN, etc.. For every single javascript value I will get it's unique type name from the classOf function. In addition I can pass in actual constructors into sjl.classOfIs to check a value's type in addition to being able to pass in it's type name as well! So for example:

``` // Please forgive long namespaces! I had no idea on the impact until after using them for a while (they suck haha)

var SomeCustomClass = sjl.package.stdlib.Extendable.extend({
    constructor: function SomeCustomClass () {},
    // ...
}),

HelloIterator = sjl.ns.stdlib.Iterator.extend( 
    function HelloIterator () {}, 
    { /* ... methods here ... */ },
    { /* ... static props/methods here ... */ }
),

helloIt = new HelloIterator();

sjl.classOfIs(new SomeCustomClass(), SomeCustomClass) === true; // `true`
sjl.classOfIs(helloIt, HelloIterator) === true; // `true`

var someString = 'helloworld';

sjl.classOfIs(someString, String) === true; // `true`

sjl.classOfIs(99, Number) === true; // true

sjl.classOf(NaN) === 'NaN'; // true

sjl.classOf(new Map()) === 'Map';
sjl.classOf(new Set()) === 'Set';
sjl.classOfIs([1, 2, 4], Array) === true; // `true`

// etc..

// Also optionally the type you want to check against could be the type's name
sjl.classOfIs(['a', 'b', 'c'], 'Array') === true; // `true`!
sjl.classOfIs(helloIt, 'HelloIterator') === true; // `true`!

```

If you are interested in reading more on how I use the setup mentioned above take a look at the repo: https://github.com/elycruz/sjljs

Also books with content on the subject: - "JavaScript Patterns" by Stoyan Stefanov. - "Javascript - The Definitive Guide." by David Flanagan. - and many others.. (search le` web).

Also you can quickly test the features I'm talking about here: - http://sjljs.elycruz.com/0.5.18/tests/for-browser/ (also the 0.5.18 path in the url has the sources from github on there minus the node_modules and such).

Happy Coding!

Pogrom answered 19/12, 2015 at 7:27 Comment(0)
S
-2

Use class.name. This also works with function.name.

class TestA {}
console.log(TestA.name); // "TestA"

function TestB() {}
console.log(TestB.name); // "TestB"
Shultz answered 28/3, 2019 at 16:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.