10

Click here to load reader

How Do I Get the Name of an Object's Type in JavaScript_ - Stack Overflow

Embed Size (px)

DESCRIPTION

getting object type name in javascript

Citation preview

  • 12/12/13 How do I get the name of an object's type in JavaScript? - Stack Overflow

    stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript 1/10

    Tell me more

    Peter Mortensen

    6,772 8 45 75

    Ewen Cartwright

    2,732 3 11 15

    13 Answers

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

    javascript

    edited Oct 4 '10 at 10:55 asked Dec 1 '08 at 22:06

    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

    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(); // create 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.

    Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, noregistration required.

    How do I get the name of an object's type in JavaScript?

    sign up

    log in

    tour

    help

    careers 2.0

    add comment

  • 12/12/13 How do I get the name of an object's type in JavaScript? - Stack Overflow

    stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript 2/10

    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 primitive values

    3 instanceof Number // false

    'abc' instanceof String // false

    true instanceof Boolean // false

    A wrapper is needed around primitives in order for instanceof to work, for example

    new Number(3) instanceof Number // true

    This is ironic because the .constructor check works fine for primitives

    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 in 1) ? results[1] : "";

    },

    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

  • 12/12/13 How do I get the name of an object's type in JavaScript? - Stack Overflow

    stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript 3/10

    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:

  • 12/12/13 How do I get the name of an object's type in JavaScript? - Stack Overflow

    stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript 4/10

    community wiki

    14 revs, 6 users 67%

    Jason Bunting

    Christian

    10.5k 3 35 81

    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. :)

    edited Jul 17 at 16:07

    88 What a thorough answer! Joshua Carmody Dec 5 '08 at 18:17

    19 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 inline with that intent, I think. Regardless, I just wanted to be somewhat thorough. Jason Bunting Dec 5 '08

    at 20:47

    2 It will work if you do it like this function a() { this.a = 1;} function b() { this.b = 2; } b.prototype = new a(); // binherits from a b.prototype.constructor = b; // Correct way of prototypical inheritance var f = new b(); //

    create new object with the b constructor (f.constructor == b); // TRUE (f.constructor == a); // FALSE

    avok00 Jan 10 '11 at 15:36

    2 Now, this is how most of the answers should be on StackOverflow. (don't take length of the answer as adefining parameter, but the comprehensiveness) Kumar Harsh Aug 12 '12 at 19:51

    7 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. Gabe Martin-Dempesy Dec 28 '12 at 16:12

    show 11 more comments

    DO NOT USE THE CONSTRUCTOR PROPERTY.

    Read THIS first.

    The correct code is:

    function get_type(thing){

    if(thing===null)return "[object Null]"; // special case

    return Object.prototype.toString.call(thing);

    }

    // example results:

    get_type(null) - [object Null]

    get_type(window) - [object Window]

    get_type([]) - [object Array]

    get_type(['1']) - [object Array]

    get_type({}) - [object Object]

    get_type(document) - [object HTMLDocument]

    get_type(document.getElementById) - [object Function]

    NB: According to specs, this function is the most reliable between different browsers.

    answered Sep 29 '10 at 21:42

    7 This isn't entirely correct: get_type(undefined);, get_type(true);, get_type(NaN);,get_type(''); and get_type(eval); imply the argument is an object while typeof undefined;,

    typeof true;, typeof NaN;, typeof ''; and typeof eval; all return something else. In

    JavaScript, type is a property of value, hence objects don't have a type but a class. The PerfectionKills blog

    post actually contains a very good implementation by extending the Object prototype with getClass.

    Saul Aug 28 '11 at 15:51

    @Saul I've read that blog, and it doesn't contradict what I said. If the OP wants cross-browser results,

    get_type is the way to go. Christian Aug 28 '11 at 22:41

    What makes you think extending Object.prototype isn't a cross-browser solution? It is supported by

    virtually every modern browser and even by IE6. Saul Aug 29 '11 at 6:25

    @Saul I never said it is not. I just said the constructor is not a cross-browser solution. The (well-deserved)

    accepted answer above uses a variation of my code as well as the PerfectionKills one. Christian Aug 29

    '11 at 8:10

    Er.. my initial comment was about extending Object.prototype not constructor. What I meant was that

    get_type gives misleading results by implying that all values in JavaScript are of object type. Saul

    Aug 29 '11 at 9:27

    show 11 more comments

  • 12/12/13 How do I get the name of an object's type in JavaScript? - Stack Overflow

    stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript 5/10

    Ewen Cartwright

    2,732 3 11 15

    Saul

    9,655 4 25 58

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

    .constructor.name

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

    function MyObject() {}

    var myInstance = new MyObject();

    myInstance.constructor.name would return "MyObject".

    edited Dec 1 '08 at 22:35 answered Dec 1 '08 at 22:21

    6 For completeness, it might be worth mentioning that using constructor.name only works if you used a namedfunction as the constructor as opposed to an anonymous function assigned to a variable.

    Matthew Crumley Dec 1 '08 at 22:24

    8 For completeness, it might worth mentioning that it doesn't work in IE browsers --- they do not support the"name" attribute on functions. Eugene Lazutkin Dec 2 '08 at 3:30

    @Eugene - I forgot about that... I guess I've spent too much time doing javascript outside browsers.

    Matthew Crumley Dec 5 '08 at 23:14

    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

    edited Jun 4 '12 at 14:43 answered Aug 28 '11 at 15:59

    Nice, but we're into naming again: JS doesn't haven't classes. mikemaccana Jun 4 '12 at 13:34

    @nailer - I recommend to use the updated function, the older one is kept for merely historic reasons. Saul

    Jun 4 '12 at 13:51

    This works but it should be noted that it could be done without modifying Object.prototype, by creating a

    function that takes the object as a first argument and uses that instead of 'this' inside the function.

    Matt Browne Nov 11 '12 at 23:23

    @Matt - Sure. It is just that having an object method is more terse: test.getClassName() vs

    getClassName.apply(test). Saul Nov 12 '12 at 7:54

    add comment

    add comment

  • 12/12/13 How do I get the name of an object's type in JavaScript? - Stack Overflow

    stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript 6/10

    ajax81

    2,838 13 27

    A little trick I use:

    function Square(){

    this.className = "Square";

    this.corners = 4;

    }

    var MySquare = new Square();

    console.log(MySquare.className); // "Square"

    edited May 13 at 0:11 answered Jun 16 '11 at 22:25

    4 I do not particularly like this. It's more a kind of dirty trick. On the other hand, if you don't have too manyconstructors, it might work just fine. pimvdb Jun 17 '11 at 7:56

    1 @pimvdb: I think it's cleaner than modifying the object's prototype, a la the accepted answer. ajax81 May13 at 0: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

    }

    }

    }

    add comment

  • 12/12/13 How do I get the name of an object's type in JavaScript? - Stack Overflow

    stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript 7/10

    Eli

    118 1 5

    Greg

    114k 20 220 261

    }

    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.

    answered Mar 5 '12 at 14:42

    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.

    answered Dec 1 '08 at 22:13

    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.. Saul Aug 29 '11 at 6:31

    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;

    add comment

    add comment

  • 12/12/13 How do I get the name of an object's type in JavaScript? - Stack Overflow

    stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript 8/10

    Peter Mortensen

    6,772 8 45 75

    farzad

    3,628 2 16 28

    Dream Factory

    496 3 10

    sblundy

    23.8k 14 67 97

    defrex

    2,243 3 18 31

    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);

    edited Oct 4 '10 at 10:58 answered Dec 2 '08 at 18:52

    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

    answered Mar 24 '12 at 12:26

    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.

    answered Dec 1 '08 at 22:22

    Yeah, sorry - I deleted it because I figured instanceof() was a better way to do things, but I just undeleted it so

    that it can serve as a reference. Jason Bunting Dec 1 '08 at 22:30

    Less than perfect answers are still useful, if only to others to come to the question later because they have a

    similar problem. So you really shouldn't delete them. Save deletes for wrong answers. sblundy Dec 1 '08 at

    22:44

    Yeah, I know - you are preaching to the choir, I have said the exact same thing to others. Living those things

    we know to be true is often harder than it looks. :) Jason Bunting Dec 1 '08 at 22:54

    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];

    };

    answered Aug 12 '11 at 19:38

    add comment

    add comment

    add comment

    add comment

  • 12/12/13 How do I get the name of an object's type in JavaScript? - Stack Overflow

    stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript 9/10

    mikemaccana

    5,046 4 32 65

    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. 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'

    answered Oct 23 at 15:04

    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 ( typeOfThing === 'object' ) {

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

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

    if ( thing.constructor.name ) {

    return thing.constructor.name;

    } else if ( thing.constructor.toString().charAt(0) === '[' ) {

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

    } else {

    add comment

    49.7k followers

    JavaScript is a dynamically-typed languagecommonly used for client-side scripting. Use thistag for questions regarding ECMAScript and itsdialects/implementations (excluding ActionScript).Unless a tag for a framew ork/library is alsoincluded, a pure JavaScript answ er is expected.

    frequent info

  • 12/12/13 How do I get the name of an object's type in JavaScript? - Stack Overflow

    stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript 10/10

    Mahdi

    2,379 1 9 28

    } 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);

    }

    answered Dec 7 at 13:00

    protected by Engineer Nov 12 at 13:42This question is protected to prevent "thanks!", "me too!", or spam answers by new users. To answer it, you must

    have earned at least 10 reputation on this site.

    Not the answer you're looking for? Browse other questions tagged javascript or ask

    your own question.

    add comment