views:

2236

answers:

4
"foo" instanceof String //=> false
"foo" instanceof Object //=> false
true instanceof Boolean //=> false
true instanceof Object //=> false
false instanceof Boolean //=> false
false instanceof Object //=> false

// the tests against Object really don't make sense

Array literals and Object literals match...

[0,1] instanceof Array //=> true
{0:1} instanceof Object //=> true

Why don't all of them? Or, why don't none of them?
And, what are they an instance of, then? Nothing()?

It's the same in FF3, IE7, Opera, and Chrome. So, at least it's consistent. ;)


Missed a few. ;)

12.21 instanceof Number //=> false
/foo/ instanceof RegExp //=> true
+10  A: 

Literals are a different kind of object than objects created from within Javascript. From the Mozilla API docs:

var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral";
color2 instanceof String; // returns false (color2 is not a String object)

I can't find any way to construct literal types with code, perhaps it's not possible. This is probably why people use typeof "foo" === "string" instead of instanceof.

An easy way to remember things like this is asking yourself "I wonder what would be sane and easy to learn"? Whatever the answer is, Javascript does the other thing.

John Millikin
That's true of string literals but not of all literals, such as object, function or array literals. Another reason for the `typeof` check rather than `instanceof` is that the `typeof` test will still work on strings from other frames or windows, or in a (admittedly contrived) situation where the `String` constructor has been overwritten.
Tim Down
+1 for humor at the end :)
allyourcode
+2  A: 

That's because those things are primitives, and unless they need to be used as objects (when you are calling methods on them, for example) they remain so. The only time they "become" objects is when they need to be wrapped. If you are familiar with the concept of "boxing" in .NET, then think of it in that way.

Here is an example - take a look at this code:

Number.prototype.times = function(func) {
   for(var index = 1; index <= this; index++) {
      func(index);
   }
};

So, the following code will fail:

3.times(print); // assume 'print' writes to standard out

3, by itself is a primitive. That said, the following will work:

(3).times(print); // assume 'print' writes to standard out

That would display the numbers 1, 2, and 3. Because of the parenthesis, the JavaScript interpreter will temporarily wrap the primitive 3 in a Number object, call the method, and then garbage collect the object since it isn't needed any longer.

Anyway, a full discussion of this can be found in "JavaScript: The Definitive Guide."

Jason Bunting
Er, no. `3.times` fails because it's a syntax error: the parser allows `3.` to be a decimal. The `()` simply removes the ambiguity, nothing to do with "boxing". Try it: `3 .times` works, as does `3..times`, as does `3. .times`.
Crescent Fresh
@Crescent, Totally agree, the parenthesis (The Grouping Operator) will not convert a primitive to Object, it will just evaluate the expression http://bclary.com/2004/11/07/#a-11.1.6
CMS
This answer is wrong, for reasons @Crescent Fresh and @CMS have already mentioned.
Tim Down
-1 because the answer is wrong
KaptajnKold
+4  A: 

You can use constructor property:

'foo'.constructor == String // returns true
true.constructor == Boolean // returns true
Note that when testing variables this technique can fail in certain circumstances. There is an implicit reference to the current window in front of `String` and `Boolean` in the above example, so if you are testing the `constructor` property of a string variable created in another window (like a popup or frame) it will _not_ be equal to simply `String`, it will be equal to `thatOtherWindowsName.String`.
Michael Mathews
A: 

Or you can just make your own function like so:

function isInstanceOf(obj, clazz){
  return (obj instanceof eval("("+clazz+")")) || (typeof obj == clazz.toLowerCase());
};

usage:

isInstanceOf('','String');
isInstanceOf(new String(), 'String');

These should both return true.

KamiMark