Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <blockquote> <p>Is there a JavaScript equivalent of Java's <code>class.getName()</code>?</p> </blockquote> <p><strong><em>No</em></strong>.</p> <p><strong>ES2015 Update</strong>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Function_names_in_classes" rel="noreferrer">the name of <code>class Foo {}</code> is <code>Foo.name</code></a>. The name of <code>thing</code>'s class, regardless of <code>thing</code>'s type, is <code>thing.constructor.name</code>. Builtin constructors in an ES2015 environment have the correct <code>name</code> property; for instance <code>(2).constructor.name</code> is <code>"Number"</code>.</p> <hr> <p>But here are various hacks that all fall down in one way or another:</p> <p>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)</p> <pre><code>Object.prototype.getName = function() { var funcNameRegex = /function (.{1,})\(/; var results = (funcNameRegex).exec((this).constructor.toString()); return (results &amp;&amp; results.length &gt; 1) ? results[1] : ""; }; </code></pre> <p>Now, all of your objects will have the function, <code>getName()</code>, that will return the name of the constructor as a string. I have tested this in <code>FF3</code> and <code>IE7</code>, I can't speak for other implementations.</p> <p>If you don't want to do that, here is a discussion on the various ways of determining types in JavaScript...</p> <hr> <p>I recently updated this to be a bit more exhaustive, though it is hardly that. Corrections welcome...</p> <h2>Using the <code>constructor</code> property...</h2> <p>Every <code>object</code> has a value for its <code>constructor</code> property, but depending on how that <code>object</code> was constructed as well as what you want to do with that value, it may or may not be useful. </p> <p>Generally speaking, you can use the <code>constructor</code> property to test the type of the object like so:</p> <pre><code>var myArray = [1,2,3]; (myArray.constructor == Array); // true </code></pre> <p>So, that works well enough for most needs. That said...</p> <h3>Caveats</h3> <p><strong>Will not work <em>AT ALL</em> in many cases</strong></p> <p>This pattern, though broken, is quite common:</p> <pre><code>function Thingy() { } Thingy.prototype = { method1: function() { }, method2: function() { } }; </code></pre> <p><code>Objects</code> constructed via <code>new Thingy</code> will have a <code>constructor</code> property that points to <code>Object</code>, not <code>Thingy</code>. So we fall right at the outset; you simply cannot trust <code>constructor</code> in a codebase that you don't control.</p> <p><strong>Multiple Inheritance</strong></p> <p>An example where it isn't as obvious is using multiple inheritance:</p> <pre><code>function a() { this.foo = 1;} function b() { this.bar = 2; } b.prototype = new a(); // b inherits from a </code></pre> <p>Things now don't work as you might expect them to:</p> <pre><code>var f = new b(); // instantiate a new object with the b constructor (f.constructor == b); // false (f.constructor == a); // true </code></pre> <p>So, you might get unexpected results if the <code>object</code> your testing has a different <code>object</code> set as its <code>prototype</code>. There are ways around this outside the scope of this discussion.</p> <p>There are other uses for the <code>constructor</code> 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.</p> <p><strong>Will not work cross-frame and cross-window</strong></p> <p>Using <code>.constructor</code> for type checking will break when you want to check the type of objects coming from different <code>window</code> objects, say that of an iframe or a popup window. This is because there's a different version of each core type <code>constructor</code> in each `window', i.e.</p> <pre><code>iframe.contentWindow.Array === Array // false </code></pre> <hr> <h2>Using the <code>instanceof</code> operator...</h2> <p>The <code>instanceof</code> operator is a clean way of testing <code>object</code> type as well, but has its own potential issues, just like the <code>constructor</code> property.</p> <pre><code>var myArray = [1,2,3]; (myArray instanceof Array); // true (myArray instanceof Object); // true </code></pre> <p>But <code>instanceof</code> fails to work for literal values (because literals are not <code>Objects</code>)</p> <pre><code>3 instanceof Number // false 'abc' instanceof String // false true instanceof Boolean // false </code></pre> <p>The literals need to be wrapped in an <code>Object</code> in order for <code>instanceof</code> to work, for example</p> <pre><code>new Number(3) instanceof Number // true </code></pre> <p>The <code>.constructor</code> check works fine for literals because the <code>.</code> method invocation implicitly wraps the literals in their respective object type</p> <pre><code>3..constructor === Number // true 'abc'.constructor === String // true true.constructor === Boolean // true </code></pre> <p>Why two dots for the 3? Because Javascript interprets the first dot as a decimal point ;)</p> <h3>Will not work cross-frame and cross-window</h3> <p><code>instanceof</code> also will not work across different windows, for the same reason as the <code>constructor</code> property check.</p> <hr> <h2>Using the <code>name</code> property of the <code>constructor</code> property...</h2> <h3>Does not work <em>AT ALL</em> in many cases</h3> <p>Again, see above; it's quite common for <code>constructor</code> to be utterly and completely wrong and useless.</p> <h3>Does NOT work in &lt;IE9</h3> <p>Using <code>myObjectInstance.constructor.name</code> will give you a string containing the name of the <code>constructor</code> function used, but is subject to the caveats about the <code>constructor</code> property that were mentioned earlier.</p> <p>For IE9 and above, you can <a href="http://matt.scharley.me/2012/03/monkey-patch-name-ie.html" rel="noreferrer">monkey-patch in support</a>:</p> <pre><code>if (Function.prototype.name === undefined &amp;&amp; Object.defineProperty !== undefined) { Object.defineProperty(Function.prototype, 'name', { get: function() { var funcNameRegex = /function\s+([^\s(]+)\s*\(/; var results = (funcNameRegex).exec((this).toString()); return (results &amp;&amp; results.length &gt; 1) ? results[1] : ""; }, set: function(value) {} }); } </code></pre> <p><strong>Updated version</strong> 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 <a href="http://matt.scharley.me/2012/03/monkey-patch-name-ie.html#comment-551654096" rel="noreferrer">comments pointing out potential pitfalls</a> in the previous code.</p> <pre><code>if (Function.prototype.name === undefined &amp;&amp; Object.defineProperty !== undefined) { Object.defineProperty(Function.prototype, 'name', { get: function() { var funcNameRegex = /function\s([^(]{1,})\(/; var results = (funcNameRegex).exec((this).toString()); return (results &amp;&amp; results.length &gt; 1) ? results[1].trim() : ""; }, set: function(value) {} }); } </code></pre> <hr> <h2>Using Object.prototype.toString</h2> <p>It turns out, as <a href="http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/" rel="noreferrer">this post details</a>, you can use <code>Object.prototype.toString</code> - the low level and generic implementation of <code>toString</code> - to get the type for all built-in types</p> <pre><code>Object.prototype.toString.call('abc') // [object String] Object.prototype.toString.call(/abc/) // [object RegExp] Object.prototype.toString.call([1,2,3]) // [object Array] </code></pre> <p>One could write a short helper function such as</p> <pre><code>function type(obj){ return Object.prototype.toString.call(obj).slice(8, -1); } </code></pre> <p>to remove the cruft and get at just the type name</p> <pre><code>type('abc') // String </code></pre> <p>However, it will return <code>Object</code> for all user-defined types.</p> <hr> <h2>Caveats for all...</h2> <p>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:</p> <pre><code>// 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 </code></pre> <p>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.</p> <h3>NOTE:</h3> <p>Discussion of the <code>typeof</code> operator may appear to be a glaring omission, but it really isn't useful in helping to identify whether an <code>object</code> is a given type, since it is very simplistic. Understanding where <code>typeof</code> 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. :)</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload