2

To clarify my title, I need a way to determine that an object is not a String, Number, Boolean, or any other predefined JavaScript object. One method that comes to mind is this:

if(!typeof myCustomObj == "string" && !typeof myCustomObj  == "number" && !typeof myCustomObj == "boolean") {

I could check to see if myCustomObj is an object, like this:

if(typeof myCustomObj == "object") {

This only works for primitive values, though, as this typeof new String("hello world") == "object") is true.

What is a reliable way to determine whether or not an object is not a predefined JavaScript object?

ajax333221
  • 11,436
  • 16
  • 61
  • 95
Elliot Bonneville
  • 51,872
  • 23
  • 96
  • 123
  • 2
    possible duplicate of [How do I get the name of an object's type in JavaScript?](http://stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript) or [The most accurate way to check JS object type?](http://stackoverflow.com/questions/7893776/the-most-accurate-way-to-check-js-object-type) –  Apr 27 '12 at 20:46
  • Now that's just not fair, how could I have known that checking an object's name would lead to me finding its type? I wouldn't have searched for "get name", I would have searched for "get type". :I – Elliot Bonneville Apr 27 '12 at 20:49
  • I just searched for *"javascript type of object"*. –  Apr 27 '12 at 20:51
  • Huh, didn't show up for me. Thanks for the other links, and sorry for asking a dup. question. – Elliot Bonneville Apr 27 '12 at 20:52

2 Answers2

5

Here's is how jQuery does it in jQuery.isPlainObject()

function (obj) {
    // Must be an Object.
    // Because of IE, we also have to check the presence of the constructor property.
    // Make sure that DOM nodes and window objects don't pass through, as well
    if (!obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow(obj)) {
        return false;
    }

    try {
        // Not own constructor property must be Object
        if (obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
            return false;
        }
    } catch(e) {
        // IE8,9 Will throw exceptions on certain host objects #9897
        return false;
    }

    // Own properties are enumerated firstly, so to speed up,
    // if last one is own, then all properties are own.
    var key;
    for (key in obj) {}

    return key === undefined || hasOwn.call(obj, key);
}
Joe
  • 80,724
  • 18
  • 127
  • 145
  • 1
    It's pretty weak, I think, that the mere presence of a property called "nodeType" would make that function return false. (That's a comment about jQuery, not about your answer :-) – Pointy Apr 27 '12 at 20:42
  • This calls other jQuery functions as well though, particularly `jQuery.type`. Any change you could dig that function out as well? Thanks. – Elliot Bonneville Apr 27 '12 at 20:42
  • 1
    @ElliotBonneville: Check out the [jQuery source viewer](http://james.padolsey.com/jquery/#v=1.6.2&fn=jQuery.isPlainObject). It'll link to the other jQuery functions :-P – gen_Eric Apr 27 '12 at 20:43
  • @ElliotBonneville: I actually just found that on Google a few hours earlier :-P – gen_Eric Apr 27 '12 at 20:45
  • Nice. @Joe Tuskan: I think this should work for me, +1 and I'll accept in a few unless somebody else posts an even more useful answer. :) – Elliot Bonneville Apr 27 '12 at 20:47
  • @ElliotBonneville: Or you can read the jQuery source on GitHub: https://github.com/jquery/jquery/blob/master/src/core.js :-) – gen_Eric Apr 27 '12 at 20:47
  • @Pointy: `$.isPlainObject({nodeType:"A"})` returns `false` :-P – gen_Eric Apr 27 '12 at 20:49
  • 2
    @Rocket yes, it's pretty clear that it would from the code above. I would kind-of understand if the name "nodeType" were something really exotic (or more specific, like "W3CDomNodeType" maybe), but "nodeType" is something one could easily use unwittingly. – Pointy Apr 27 '12 at 20:57
  • -1 This answer ultimately relies on both public and internal code in jQuery. –  Apr 27 '12 at 21:04
  • @amnotiam, you again. Awesome. This is a public method in jQuery. The code demonstrates the inner workings. But seriously man what's your problem? – Joe Apr 27 '12 at 23:11
  • I don't have a problem. Just pointing out that it will fail for future readers who try to run the code. Yes, `jQuery.type` is public, but I don't see how that's useful to some future reader who tries to run the code and sees that it doesn't work as shown. Also, the `hasOwn` method is an [internal reference to `Object.prototype.hasOwnProperty`](https://github.com/jquery/jquery/blob/1.7.1/src/core.js#L67), which will again cause someone running your code to fail. The answer just simply doesn't work as shown. –  Apr 28 '12 at 00:06
  • @amnotiam, again you are in some other area of thought. I answered the question poorly true just saying there is a jQuery method to test this. I never said, run this internal jQuery code. I posted the code for a peek into how jQuery was accomplishing this. Honestly, can you tell me how you would answer this question? – Joe Apr 28 '12 at 00:36
  • And based on everything you just described in your comment above, I felt this answer was worth -1, especially since it was so highly upvoted, which didn't seem at all reasonable to me. Not that big of a deal, is it? I just don't think it really provides much of a solution overall. My answer was to vote to close as a duplicate, but I would answer it [more like this](http://stackoverflow.com/a/10357501/1106925). –  Apr 28 '12 at 00:49
4

You can use the "toString" functon on the Object prototype:

var typ = Object.prototype.toString.call( someTestObject );

That gives answers like "[object String]" or "[object Date]" for the built-in types. Unfortunately you can't distinguish that way between things created as plain Object instances and things made with a constructor, but in a sense those things aren't really that much different anyway.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Unfortunately, I need to detect plain Object instances that have custom properties on them as different from built-in types as well, so I don't know if this will work for me. – Elliot Bonneville Apr 27 '12 at 20:46
  • The answer with the jQuery approach is pretty thorough. – Pointy Apr 27 '12 at 20:49
  • `Object.prototype.toString.call($())` returns `[object Object]`, but `$.isPlainObject($())` returns `false`. Just FYI :-P +1 for this, it should work in most cases, unless you need to be really specific. – gen_Eric Apr 27 '12 at 20:50