6

To check if an element is an array in JavaScript, I have always used Crockford's function (pg 61 of The Good Parts):

var is_array = function (value) {
    return value &&
        typeof value === 'object' &&
        typeof value.length === 'number' &&
        typeof value.splice === 'function' &&
        !(value.propertyIsEnumerable('length'));
}

But if I'm not mistaken, recently some guy from Google had found a new way on how to test for a JavaScript array, but I just can't remember from where I read it and how the function went.

Can anyone point me to his solution please?


[Update]
The person from Google who apparently discovered this is called Mark Miller.

Now I've also read that from this post that his solution can easily break as well:

// native prototype overloaded, some js libraries extends them
Object.prototype.toString= function(){
  return  '[object Array]';
}

function isArray ( obj ) {
  return Object.prototype.toString.call(obj) === '[object Array]';
}

var a = {};
alert(isArray(a)); // returns true, expecting false;

So, I ask, is there any way that we can truly check for array validity?

Andreas Grech
  • 105,982
  • 98
  • 297
  • 360
  • Possible duplicates: http://stackoverflow.com/questions/1202841/ http://stackoverflow.com/questions/1058427 – Christian C. Salvadó Nov 18 '09 at 22:13
  • 4
    @Andreas: if you stab yourself in the eye, don't wonder why you're going blind... – Christoph Nov 18 '09 at 23:00
  • ah haha; ure talking about messing with the `Object.prototype` ? – Andreas Grech Nov 18 '09 at 23:00
  • 1
    @Andreas: yes; extending `Object.prototype` is (or would be) ok as long as everyone remembers to check `hasOwnProperty()`, but overwriting native methods definitely is a big NO-NO; the only valid reason to do this is to fix bugs/non-standard behaviour (*cough* JScript *cough*) – Christoph Nov 18 '09 at 23:13
  • I agree with you completely, but the problem is that certain libraries tend to extend the Object prototype...which will then screw up your code – Andreas Grech Nov 18 '09 at 23:16
  • I endeavor never to need to know. – Nosredna Nov 18 '09 at 23:20

2 Answers2

7

I believe you are looking for

Object.prototype.toString.call(value) === "[object Array]";

This is the method that jQuery uses to check whether a passed parameter value is a function or array object. There are browser specific instances where using typeof does not yield the correct result

Russ Cam
  • 124,184
  • 33
  • 204
  • 266
  • 1
    FYI the second example is not a valid shorthand. jQuery creates a local `toString` reference that simply points to `Object.prototype.toString`. – Crescent Fresh Nov 18 '09 at 22:18
  • Doesn't jQuery define it as a local reference to resolve the call quicker? Since all objects derive from Object, they should all have the toString function – Russ Cam Nov 18 '09 at 22:22
  • @Russ: heh, sorry I think we're just saying the same thing. You're right, jQuery simply does `var toString = Object.prototype.toString;`. My point was `Object.prototype.toString !== window.toString`, which invalidates your statement that the second example is equivalent to the first example, that's all :) Cheers. – Crescent Fresh Nov 18 '09 at 22:28
  • You could of course, define a toString function on the constructor's prototype and break the shorthand, so duly noted, will remove the shorthand :) – Russ Cam Nov 18 '09 at 22:29
-1

You could do this:

t = [1,2];
// Now to check if this is an array
if (t.constructor == Array)
{
    alert('t is an array');
}
else
{
    alert('t is NOT an array');
}

Basically, variable.constructor == Array

Aishwar
  • 9,284
  • 10
  • 59
  • 80
  • That fails as well, for the same reasons I told @tyranid. Read the section 'Detecting Object and Array' at this post: http://www.karmagination.com/blog/2009/07/29/javascript-kung-fu-object-array-and-literals/ – Andreas Grech Nov 18 '09 at 22:48