49

Possible Duplicate:
How to detect if a variable is an array

I have a simple question:

How do I detect if a parameter passed to my javascript function is an array? I don't believe that I can test:

if (typeof paramThatCouldBeArray == 'array') 

So is it possible?

How would I do it?

Thanks in advance.

Community
  • 1
  • 1
Alex
  • 64,178
  • 48
  • 151
  • 180
  • Hmm...that makes me think. Maybe my function design is bad if it could possibly be passed anything else. But I was more asking this because of `console.log()`. It intrigues me because if you pass it an array, it iterates over the whole array and prints it out. While if you just pass it a single string, it just logs that. How does it do this? – Alex May 04 '10 at 05:42
  • Sorry, for continuity, deleted comment was "What other types could the parameter be?" – Casey Chu May 04 '10 at 05:43
  • @Alex: in which browser? It could be relying on `Array.toString`. – outis May 04 '10 at 05:44
  • They seem to be using a lot of browser-dependent checks -- inspect line 1992 at http://getfirebug.com/releases/lite/1.2/firebug-lite.js – Casey Chu May 04 '10 at 05:51
  • @Alex: note that in Chrome, `console.log` is a native function, and thus has access to info not accessible to a JS script. – outis May 04 '10 at 06:27
  • ... Firebug uses things it calls "representations" (http://code.google.com/p/fbug/source/browse/branches/firebug1.6/content/firebug/console.js#sl_svn6639_455, http://code.google.com/p/fbug/source/browse/branches/firebug1.6/content/firebug/reps.js) to convert objects, each of which has a `supportsObject` method, which mostly use `instanceof` (e.g. http://code.google.com/p/fbug/source/browse/branches/firebug1.6/content/firebug/reps.js#sl_svn6588_550). Firebug Lite (http://code.google.com/p/fbug/source/browse/branches/firebug1.6/lite/firebug.js) indirectly uses `toString` (it calls `obj + ''`). – outis May 04 '10 at 06:27

6 Answers6

72
if (param instanceof Array)
    ...

Edit. As of 2016, there is a ready-built method that catches more corner cases, Array.isArray, used as follows:

if (Array.isArray(param))
    ...
Casey Chu
  • 25,069
  • 10
  • 40
  • 59
  • 8
    Good for most cases, but it wont work on cross-frame environments, give a look to this [article](http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/). – Christian C. Salvadó May 04 '10 at 06:25
  • 3
    `!!param.shift` would be faster in terms of execution speed. http://jsperf.com/instanceof-vs-method-detect – Bart May 27 '14 at 10:01
  • 1
    Is it safe to assume this will work properly under nodejs (as there is only one frame i guess ) ? – 131 Sep 19 '14 at 07:03
  • 2
    If you know for sure you won't be operating across frames (as is generally the case), then use the constructor method. Performance comparison: http://jsperf.com/detecting-arrays-new – thdoan Jan 30 '15 at 03:30
  • As of 2016, this is still a generally performant and reliable solution. – T.W.R. Cole Jun 07 '16 at 19:24
19

This is the approach jQuery 1.4.2 uses:

var toString = param.prototype.toString;
var isArray = function(obj) {
        return toString.call(obj) === "[object Array]";
    }
James Westgate
  • 11,306
  • 8
  • 61
  • 68
  • 1
    This `toString` comparison may seem strange but it is the accepted way to deal with cross-frame environments. – Halcyon Nov 23 '11 at 12:53
  • I don't quite understand: I define `toString` based on `param`, and then I call `isArray()`? What do I pass as `obj`? Where is the bottom line of this answer? – Tom Aug 21 '12 at 17:15
  • Tom, basically every object has a toString function which is 'overridden' for an array and per the spec returns [object Array]. This is uniform across all js implementations. The prototype is just so that one function is referenced. – James Westgate Aug 22 '12 at 09:15
  • 3
    What if param is the string "[object Array]" ? I think calling toString on a string returns the string itself –  Jan 25 '17 at 09:34
5

I found this here:

function isArray(obj) {
    return obj.constructor == Array; 
}

also this one

function isArray(obj) {
    return (obj.constructor.toString().indexOf(”Array”) != -1);
}
Germán Rodríguez
  • 4,284
  • 1
  • 19
  • 19
  • Testing with JScript `obj.constructor.toString()` returns `function Array() { [native code] }`, making this solution work for that environment. – tresf Oct 25 '18 at 01:49
1

You can test the constructor property:

if (param.constructor == Array) {
    ...
}

Though this will include objects that have an array prototype,

function Stack() {
}
Stack.prototype = [];

unless they also define constructor:

Stack.prototype.constructor = Stack;

or:

function Stack() {
    this.constructor = Stack;
}
outis
  • 75,655
  • 22
  • 151
  • 221
1

Some days ago I was building a simple type detection function, maybe its useful for you:

Usage:

//...
if (typeString(obj) == 'array') {
  //..
}

Implementation:

function typeString(o) {
  if (typeof o != 'object')
    return typeof o;

  if (o === null)
      return "null";
  //object, array, function, date, regexp, string, number, boolean, error
  var internalClass = Object.prototype.toString.call(o)
                                               .match(/\[object\s(\w+)\]/)[1];
  return internalClass.toLowerCase();
}

The second variant of this function is more strict, because it returns only object types described in the ECMAScript specification (possible output values: "object", "undefined", "null", and "function", "array", "date", "regexp", "string", "number", "boolean" "error", using the [[Class]] internal property).

Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
-1

Duck Typying

Actually, you don't necessarily want to check that an object is an array. You should duck type it and the only thing you want that object to implement is the length property. After this you can transform it into an array:

var arrayLike = {
    length : 3,

    0: "foo"
};

// transform object to array
var array = Array.prototype.slice.call(arrayLike);

JSON.stringify(array); // ["foo", null, null]

Array.prototype.slice.call(object) will transform into an array every object that exposes a length property. In the case of strings for example:

var array = Array.prototype.slice.call("123");
JSON.stringify(array); // ["1", "2", "3"]

Well, this technique it's not quite working on IE6 (I don't know about later versions), but it's easy to create a small utility function to transform objects in arrays.

Community
  • 1
  • 1
Ionuț G. Stan
  • 176,118
  • 18
  • 189
  • 202