How can I check if an object is an array? [duplicate]

Asked 2023-09-20 20:18:14 View 299,526

I'm trying to write a function that either accepts a list of strings, or a single string. If it's a string, then I want to convert it to an array with just the one item so I can loop over it without fear of an error.

So how do I check if the variable is an array?

  • I thought you meant to 'check if object is an array', but you want to check if 'object is an array of strings or a single string' specifically. Not sure if you see it? Or is it just me? I was thinking of something more like this... am I the one missing something here? - anyone
  • TL;DR - arr.constructor === Array is fastest. - anyone
  • jsben.ch/#/QgYAV - a benchmark for the most common ways - anyone
  • TL;DR - Array.isArray(arr) since ES5; and $.isArray(arr) in jQuery. - anyone
  • Just bear in mind that if you by any reason overwrite your constructor via prototype that arr.constructor === Array test will return false. Array.isArray(arr) still returns true though. - anyone

Answers

The method given in the ECMAScript standard to find the class of Object is to use the toString method from Object.prototype.

if(Object.prototype.toString.call(someVar) === '[object Array]') {
    alert('Array!');
}

Or you could use typeof to test if it is a string:

if(typeof someVar === 'string') {
    someVar = [someVar];
}

Or if you're not concerned about performance, you could just do a concat to a new empty Array.

someVar = [].concat(someVar);

There's also the constructor which you can query directly:

if (somevar.constructor.name == "Array") {
    // do something
}

Check out a thorough treatment from T.J. Crowder's blog, as posted in his comment below.

Check out this benchmark to get an idea which method performs better: http://jsben.ch/#/QgYAV

From @Bharath, convert a string to an array using ES6 for the question asked:

const convertStringToArray = (object) => {
   return (typeof object === 'string') ? Array(object) : object
}

Suppose:

let m = 'bla'
let n = ['bla','Meow']
let y = convertStringToArray(m)
let z = convertStringToArray(n)
console.log('check y: '+JSON.stringify(y)) . // check y: ['bla']
console.log('check y: '+JSON.stringify(z)) . // check y: ['bla','Meow']

Answered   2023-09-20 20:18:14

In modern browsers you can do:

Array.isArray(obj)

(Supported by Chrome 5, Firefox 4.0, Internet Explorer 9, Opera 10.5 and Safari 5)

For backward compatibility you can add the following:

// Only implement if no native implementation is available
if (typeof Array.isArray === 'undefined') {
  Array.isArray = function(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
  }
};

If you use jQuery you can use jQuery.isArray(obj) or $.isArray(obj). If you use Underscore.js you can use _.isArray(obj).

If you don't need to detect arrays created in different frames you can also just use instanceof:

obj instanceof Array

Answered   2023-09-20 20:18:14

  • Here is a more complete list of browsers that support Array.isArray - anyone
  • @NobleUplift: instanceof Array fails if the array is from a different frame because every array from that different frame has a different Array constructor and prototype. For compatibility/security reasons, every frame has its own global environment, and this includes global objects. The Object global from one frame is different from the Object global from another. So too for Array globals. Axel Rauschmayer talks more about this. - anyone
  • Note that, as of 2022, this is very well supported (even back many browser versions): caniuse.com/?search=isArray And also now the fastest method: jsben.ch/QgYAV - anyone

I would first check if your implementation supports isArray:

if (Array.isArray)
    return Array.isArray(v);

You could also try using the instanceof operator

v instanceof Array

Answered   2023-09-20 20:18:14

  • v instanceof Array will return false if v was created in another frame (v is instance of thatFrame.contentWindow.Array class). - anyone
  • To be specific: Array.isArray is defined as part of ECMAScript 5/Javascript 1.8.5. - anyone

jQuery also offers an $.isArray() method:

var a = ["A", "AA", "AAA"];

if($.isArray(a)) {
  alert("a is an array!");
} else {
  alert("a is not an array!");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Answered   2023-09-20 20:18:14

This is the fastest among all methods (all browsers supported):

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

Answered   2023-09-20 20:18:14

Imagine you have this array below:

var arr = [1,2,3,4,5];

JavaScript (new and older browsers):

function isArray(arr) {
  return arr.constructor.toString().indexOf("Array") > -1;
}

or

function isArray(arr) {
  return arr instanceof Array;
}

or

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

Then call it like this:

isArray(arr);

JavaScript (Internet Explorer 9+, Chrome 5+, Firefox 4+, Safari 5+, and Opera 10.5+)

Array.isArray(arr);

jQuery:

$.isArray(arr);

Angular:

angular.isArray(arr);

Underscore.js and Lodash:

_.isArray(arr);

Answered   2023-09-20 20:18:14

Array.isArray works fast, but it isn't supported by all versions of browsers.

So you could make an exception for others and use a universal method:

    Utils = {};
    Utils.isArray = ('isArray' in Array) ?
        Array.isArray :
        function (value) {
            return Object.prototype.toString.call(value) === '[object Array]';
        }

Answered   2023-09-20 20:18:14

A simple function to check this:

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

Answered   2023-09-20 20:18:14

  • I'd reduce that down to one line return object.constructor === Array -- but are you sure that this will only return true for arrays? - anyone
  • Can do that with all boolean expressions. Drives me nuts when I see if(x) return true; else return false :-) Even if it's backwards, you should negate the expression. - anyone
  • This fails badly if object is undefined or null. - anyone

You can use Array.isArray(). Here is a polyfill:

if (Array.isArray == null) {
  Array.isArray = (arr) => Object.prototype.toString.call(arr) === "[object Array]"
}

Answered   2023-09-20 20:18:14

  • Can you elaborate a little bit? E.g., why is "Array.isArray" on both sides of the "="? "Array.isArray" is a method. What is the principle of operation? Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today). - anyone

As MDN says in here:

use Array.isArray or Object.prototype.toString.call to differentiate regular objects from arrays

Like this:

  • Object.prototype.toString.call(arr) === '[object Array]', or

  • Array.isArray(arr)

Answered   2023-09-20 20:18:14

There's just one line solution for this question

x instanceof Array

where x is the variable it will return true if x is an array and false if it is not.

Answered   2023-09-20 20:18:14

I would make a function to test the type of object you are dealing with...

function whatAmI(me){ return Object.prototype.toString.call(me).split(/\W/)[2]; }

// tests
console.log(
  whatAmI(["aiming","@"]),
  whatAmI({living:4,breathing:4}),
  whatAmI(function(ing){ return ing+" to the global window" }),
  whatAmI("going to do with you?")
);

// output: Array Object Function String

then you can write a simple if statement...

if(whatAmI(myVar) === "Array"){
    // do array stuff
} else { // could also check `if(whatAmI(myVar) === "String")` here to be sure
    // do string stuff
}

Answered   2023-09-20 20:18:14

You can check the type of your variable whether it is an array with;

var myArray=[];

if(myArray instanceof Array)
{
....
}

Answered   2023-09-20 20:18:14

  • A few people have already mentioned instanceof.. I think it fails under a few weird scenarios. - anyone

I do this in a very simple way. It works for me.

Array.prototype.isArray = true;

a=[]; b={};
a.isArray  // true
b.isArray  // (undefined -> false)

Answered   2023-09-20 20:18:14

  • fooled by {isArray:true} - anyone
  • JSON.parse(someDataFromElsewhere).items.isArray could return true (depending on the data) and break your code. - anyone

This is my attempt to improve on this answer taking into account the comments:

var isArray = myArray && myArray.constructor === Array;

It gets rid of the if/else, and accounts for the possibility of the array being null or undefined

Answered   2023-09-20 20:18:14

  • constructor is not available in ES5 - anyone

I have updated the jsperf fiddle with two alternative methods as well as error checking.

It turns out that the method defining a constant value in the 'Object' and 'Array' prototypes is faster than any of the other methods. It is a somewhat surprising result.

/* Initialisation */
Object.prototype.isArray = function() {
  return false;
};
Array.prototype.isArray = function() {
  return true;
};
Object.prototype._isArray = false;
Array.prototype._isArray = true;

var arr = ["1", "2"];
var noarr = "1";

/* Method 1 (function) */
if (arr.isArray()) document.write("arr is an array according to function<br/>");
if (!noarr.isArray()) document.write("noarr is not an array according to function<br/>");
/* Method 2 (value) - **** FASTEST ***** */
if (arr._isArray) document.write("arr is an array according to member value<br/>");
if (!noarr._isArray) document.write("noarr is not an array according to member value<br/>");

These two methods do not work if the variable takes the undefined value, but they do work if you are certain that they have a value. With regards to checking with performance in mind if a value is an array or a single value, the second method looks like a valid fast method. It is slightly faster than 'instanceof' on Chrome, twice as fast as the second best method in Internet Explorer, Opera and Safari (on my machine).

Answered   2023-09-20 20:18:14

I know, that people are looking for some kind of raw JavaScript approach. But if you want think less about it, take a look at Underscore.js' isArray:

_.isArray(object)

It returns true if object is an Array.

(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true

Answered   2023-09-20 20:18:14

  • "Unless another tag for a framework/library is also included, a pure JavaScript answer is expected." - anyone

The best practice is to compare it using constructor, something like this

if(some_variable.constructor === Array){
  // do something
}

You can use other methods too, like typeOf, converting it to a string and then comparing, but comparing it with dataType is always a better approach.

Answered   2023-09-20 20:18:14

The best solution I've seen is a cross-browser replacement for typeof. Check Angus Croll's solution.

The TL;DR version is below, but the article is a great discussion of the issue so you should read it if you have time.

Object.toType = function(obj) {
    return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
}
// ... and usage:
Object.toType([1,2,3]); //"array" (all browsers)

// or to test...
var shouldBeAnArray = [1,2,3];
if(Object.toType(shouldBeAnArray) === 'array'){/* do stuff */};

Answered   2023-09-20 20:18:14

If the only two kinds of values that could be passed to this function are a string or an array of strings, keep it simple and use a typeof check for the string possibility:

function someFunc(arg) {
    var arr = (typeof arg == "string") ? [arg] : arg;
}

Answered   2023-09-20 20:18:14

  • Yeah... that'd work for this scenario, but not in general. Ended up using varargs anyway. :) - anyone

Here's my lazy approach:

if (Array.prototype.array_ === undefined) {
  Array.prototype.array_ = true;
}

// ...

var test = [],
    wat = {};

console.log(test.array_ === true); // true
console.log(wat.array_ === true);  // false

I know it's sacrilege to "mess with" the prototype, but it appears to perform significantly better than the recommended toString method.

Note: A pitfall of this approach is that it wont work across iframe boundaries, but for my use case this is not an issue.

Answered   2023-09-20 20:18:14

  • its not better in terms of performance anymore, at least on FF30 on Ubuntu 64-bit - anyone
  • fooled by wat = {array_: true} objects. - anyone
  • @Bergi: Yes, that should be obvious. If you're setting obj.array_ = true, then you're only fooling yourself. - anyone
  • @namuol: I'm not necessarily fooling myself. Often enough objects are used as dictionaries. Think of a cache object to memoize search results which uses the search strings as property keys. What if a user searches for array_? Does your object become an array because of that? It's just a bug. - anyone
  • @namuol: Also, this approach would require that all involved parties (including used libraries) can agree that .array_ is used for tagging arrays. That's really not the case here, .array can mean anything. You should at least use a descriptive string, and signal inappropriateness of arbitrary use, e.g. with .__isArray = true. - anyone

This function will turn almost anything into an array:

function arr(x) {
    if(x === null || x === undefined) {
        return [];
    }
    if(Array.isArray(x)) {
        return x;
    }
    if(isString(x) || isNumber(x)) {
        return [x];
    }
    if(x[Symbol.iterator] !== undefined || x.length !== undefined) {
        return Array.from(x);
    }
    return [x];
}

function isString(x) {
    return Object.prototype.toString.call(x) === "[object String]"
}

function isNumber(x) {
    return Object.prototype.toString.call(x) === "[object Number]"
}

It uses some newer browser features so you may want to polyfill this for maximum support.

Examples:

> arr(null);
[]
> arr(undefined)
[]
> arr(3.14)
[ 3.14 ]
> arr(1/0)
[ Infinity ]
> gen = function*() { yield 1; yield 2; yield 3; }
[Function: gen]
> arr(gen())
[ 1, 2, 3 ]
> arr([4,5,6])
[ 4, 5, 6 ]
> arr("foo")
[ 'foo' ]

N.B. strings will be converted into an array with a single element instead of an array of chars. Delete the isString check if you would prefer it the other way around.

I've used Array.isArray here because it's the most robust and also simplest.

Answered   2023-09-20 20:18:14

The following could be used if you know that your object doesn't have a concat method.

var arr = [];
if (typeof arr.concat === 'function') {
    console.log("It's an array");
}

Answered   2023-09-20 20:18:14

  • This is a good trick, but could be overridden... but most of the times should get the result - anyone
var a = [], b = {};

console.log(a.constructor.name == "Array");
console.log(b.constructor.name == "Object");

Answered   2023-09-20 20:18:14

  • Hi, thanks for your answer. Code only answers tend to be overlooked, would you mind adding some explanation to your code? - anyone

There is a nice example in Stoyan Stefanov's book JavaScript Patterns which is supposed to handle all possible problems as well as use the ECMAScript 5 method Array.isArray().

So here it is:

if (typeof Array.isArray === "undefined") {
    Array.isArray = function (arg) {
        return Object.prototype.toString.call(arg) === "[object Array]";
    };
}

By the way, if you are using jQuery, you can use its method $.isArray().

Answered   2023-09-20 20:18:14

  • +1: why not just a simple if(!Array.isArray) {... ? - anyone

You could use the isArray method, but I would prefer to check with:

Object.getPrototypeOf(yourvariable) === Array.prototype

Answered   2023-09-20 20:18:14

  • Why would you prefer this? - anyone
  • @mpen Object.getPrototypeOf(yourvariable) it returns prototype of an Array object. And The code is fastest and safe to rely on. - anyone
  • It's easy to foil: pastebin.com/MP8d5bCE Also, do you have performance tests to back up your "fastest" claim? - anyone
function isArray(value) {
    if (value) {
        if (typeof value === 'object') {
            return (Object.prototype.toString.call(value) == '[object Array]')
        }
    }
    return false;
}

var ar = ["ff","tt"]
alert(isArray(ar))

Answered   2023-09-20 20:18:14

  • An explanation would be in order. Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today). - anyone

A simple function for testing if an input value is an array is the following:

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

This works cross browser, and with older browsers. This is pulled from T.J. Crowders' blog post

Answered   2023-09-20 20:18:14

You can try this:

var arr = []; (or) arr = new Array();
var obj = {}; (or) arr = new Object();

arr.constructor.prototype.hasOwnProperty('push') //true

obj.constructor.prototype.hasOwnProperty('push') // false

Answered   2023-09-20 20:18:14

In your case you may use concat method of Array which can accept single objects as well as array (and even combined):

function myFunc(stringOrArray)
{
  var arr = [].concat(stringOrArray);

  console.log(arr);

  arr.forEach(function(item, i)
  {
    console.log(i, "=", item);
  })
}

myFunc("one string");

myFunc(["one string", "second", "third"]);

concat seems to be one of the oldest methods of Array (even IE 5.5 knows it well).

Answered   2023-09-20 20:18:14