How do I check if a variable is an array in JavaScript?
if (variable.constructor == Array)
There are several ways of checking if an variable is an array or not. The best solution is the one you have chosen.
variable.constructor === Array
This is the fastest method on Chrome, and most likely all other browsers. All arrays are objects, so checking the constructor property is a fast process for JavaScript engines.
If you are having issues with finding out if an objects property is an array, you must first check if the property is there.
variable.prop && variable.prop.constructor === Array
Some other ways are:
Array.isArray(variable)
Update May 23, 2019 using Chrome 75, shout out to #AnduAndrici for having me revisit this with his question
This last one is, in my opinion the ugliest, and it is one of the slowest fastest. Running about 1/5 the speed as the first example. This guy is about 2-5% slower, but it's pretty hard to tell. Solid to use! Quite impressed by the outcome. Array.prototype, is actually an array. you can read more about it here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
variable instanceof Array
This method runs about 1/3 the speed as the first example. Still pretty solid, looks cleaner, if you're all about pretty code and not so much on performance. Note that checking for numbers does not work as variable instanceof Number always returns false. Update: instanceof now goes 2/3 the speed!
So yet another update
Object.prototype.toString.call(variable) === '[object Array]';
This guy is the slowest for trying to check for an Array. However, this is a one stop shop for any type you're looking for. However, since you're looking for an array, just use the fastest method above.
Also, I ran some test: http://jsperf.com/instanceof-array-vs-array-isarray/35 So have some fun and check it out.
Note: #EscapeNetscape has created another test as jsperf.com is down. http://jsben.ch/#/QgYAV I wanted to make sure the original link stay for whenever jsperf comes back online.
You could also use:
if (value instanceof Array) {
alert('value is Array!');
} else {
alert('Not an array');
}
This seems to me a pretty elegant solution, but to each his own.
Edit:
As of ES5 there is now also:
Array.isArray(value);
But this will break on older browsers, unless you are using polyfills (basically... IE8 or similar).
There are multiple solutions with all their own quirks. This page gives a good overview. One possible solution is:
function isArray(o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
In modern browsers (and some legacy browsers), you can do
Array.isArray(obj)
(Supported by Chrome 5, Firefox 4.0, IE 9, Opera 10.5 and Safari 5)
If you need to support older versions of IE, you can use es5-shim to polyfill Array.isArray; or 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 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
Note: the arguments keyword that can be used to access the argument of a function isn't an Array, even though it (usually) behaves like one:
var func = function() {
console.log(arguments) // [1, 2, 3]
console.log(arguments.length) // 3
console.log(Array.isArray(arguments)) // false !!!
console.log(arguments.slice) // undefined (Array.prototype methods not available)
console.log([3,4,5].slice) // function slice() { [native code] }
}
func(1, 2, 3)
I noticed someone mentioned jQuery, but I didn't know there was an isArray() function. It turns out it was added in version 1.3.
jQuery implements it as Peter suggests:
isArray: function( obj ) {
return toString.call(obj) === "[object Array]";
},
Having put a lot of faith in jQuery already (especially their techniques for cross-browser compatibility) I will either upgrade to version 1.3 and use their function (providing that upgrading doesn’t cause too many problems) or use this suggested method directly in my code.
Many thanks for the suggestions.
This is an old question but having the same problem i found a very elegant solution that i want to share.
Adding a prototype to Array makes it very simple
Array.prototype.isArray = true;
Now once if you have an object you want to test to see if its an array all you need is to check for the new property
var box = doSomething();
if (box.isArray) {
// do something
}
isArray is only available if its an array
Via Crockford:
function typeOf(value) {
var s = typeof value;
if (s === 'object') {
if (value) {
if (value instanceof Array) {
s = 'array';
}
} else {
s = 'null';
}
}
return s;
}
The main failing Crockford mentions is an inability to correctly determine arrays that were created in a different context, e.g., window.
That page has a much more sophisticated version if this is insufficient.
If you're only dealing with EcmaScript 5 and above then you can use the built in Array.isArray function
e.g.,
Array.isArray([]) // true
Array.isArray("foo") // false
Array.isArray({}) // false
I personally like Peter's suggestion: https://stackoverflow.com/a/767499/414784 (for ECMAScript 3. For ECMAScript 5, use Array.isArray())
Comments on the post indicate, however, that if toString() is changed at all, that way of checking an array will fail. If you really want to be specific and make sure toString() has not been changed, and there are no problems with the objects class attribute ([object Array] is the class attribute of an object that is an array), then I recommend doing something like this:
//see if toString returns proper class attributes of objects that are arrays
//returns -1 if it fails test
//returns true if it passes test and it's an array
//returns false if it passes test and it's not an array
function is_array(o)
{
// make sure an array has a class attribute of [object Array]
var check_class = Object.prototype.toString.call([]);
if(check_class === '[object Array]')
{
// test passed, now check
return Object.prototype.toString.call(o) === '[object Array]';
}
else
{
// may want to change return value to something more desirable
return -1;
}
}
Note that in JavaScript The Definitive Guide 6th edition, 7.10, it says Array.isArray() is implemented using Object.prototype.toString.call() in ECMAScript 5. Also note that if you're going to worry about toString()'s implementation changing, you should also worry about every other built in method changing too. Why use push()? Someone can change it! Such an approach is silly. The above check is an offered solution to those worried about toString() changing, but I believe the check is unnecessary.
When I posted this question the version of JQuery that I was using didn't include an isArray function. If it had have I would have probably just used it trusting that implementation to be the best browser independant way to perform this particular type check.
Since JQuery now does offer this function, I would always use it...
$.isArray(obj);
(as of version 1.6.2) It is still implemented using comparisons on strings in the form
toString.call(obj) === "[object Array]"
Thought I would add another option for those who might already be using the Underscore.js library in their script. Underscore.js has an isArray() function (see http://underscorejs.org/#isArray).
_.isArray(object)
Returns true if object is an Array.
If you are using Angular, you can use the angular.isArray() function
var myArray = [];
angular.isArray(myArray); // returns true
var myObj = {};
angular.isArray(myObj); //returns false
http://docs.angularjs.org/api/ng/function/angular.isArray
In Crockford's JavaScript The Good Parts, there is a function to check if the given argument is an array:
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
He explains:
First, we ask if the value is truthy. We do this to reject null and other falsy values. Second, we ask if the typeof value is 'object'. This will be true for objects, arrays, and (weirdly) null. Third, we ask if the value has a length property that is a number. This will always be true for arrays, but usually not for objects. Fourth, we ask if the value contains a splice method. This again will be true for all arrays. Finally, we ask if the length property is enumerable (will length be produced by a for in loop?). That will be false for all arrays. This is the most reliable test for arrayness that I have found. It is unfortunate that it is so complicated.
The universal solution is below:
Object.prototype.toString.call(obj)=='[object Array]'
Starting from ECMAScript 5, a formal solution is :
Array.isArray(arr)
Also, for old JavaScript libs, you can find below solution although it's not accurate enough:
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
The solutions are from http://www.pixelstech.net/topic/85-How-to-check-whether-an-object-is-an-array-or-not-in-JavaScript
For those who code-golf, an unreliable test with fewest characters:
function isArray(a) {
return a.map;
}
This is commonly used when traversing/flattening a hierarchy:
function golf(a) {
return a.map?[].concat.apply([],a.map(golf)):a;
}
input: [1,2,[3,4,[5],6],[7,[8,[9]]]]
output: [1, 2, 3, 4, 5, 6, 7, 8, 9]
code referred from https://github.com/miksago/Evan.js/blob/master/src/evan.js
var isArray = Array.isArray || function(obj) {
return !!(obj && obj.concat && obj.unshift && !obj.callee);};
I was using this line of code:
if (variable.push) {
// variable is array, since AMAIK only arrays have push() method.
}
I have created this little bit of code, which can return true types.
I am not sure about performance yet, but it's an attempt to properly identify the typeof.
https://github.com/valtido/better-typeOf also blogged a little about it here http://www.jqui.net/jquery/better-typeof-than-the-javascript-native-typeof/
it works, similar to the current typeof.
var user = [1,2,3]
typeOf(user); //[object Array]
It think it may need a bit of fine tuning, and take into account things, I have not come across or test it properly. so further improvements are welcomed, whether it's performance wise, or incorrectly re-porting of typeOf.
I think using myObj.constructor==Object and myArray.constructor==Array is the best way. Its almost 20x faster than using toString(). If you extend objects with your own constructors and want those creations to be considered "objects" as well than this doesn't work, but otherwise its way faster. typeof is just as fast as the constructor method but typeof []=='object' returns true which will often be undesirable. http://jsperf.com/constructor-vs-tostring
one thing to note is that null.constructor will throw an error so if you might be checking for null values you will have to first do if(testThing!==null){}
From w3schools:
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
I liked the Brian answer:
function is_array(o){
// make sure an array has a class attribute of [object Array]
var check_class = Object.prototype.toString.call([]);
if(check_class === '[object Array]') {
// test passed, now check
return Object.prototype.toString.call(o) === '[object Array]';
} else{
// may want to change return value to something more desirable
return -1;
}
}
but you could just do like this:
return Object.prototype.toString.call(o) === Object.prototype.toString.call([]);
I tried most of the solutions here. But none of them worked. Then I came up with a simple solution. Hope it will help someone & save their time.
if(variable.constructor != undefined && variable.constructor.length > 0) {
/// IT IS AN ARRAY
} else {
/// IT IS NOT AN ARRAY
}
Since the .length property is special for arrays in javascript you can simply say
obj.length === +obj.length // true if obj is an array
Underscorejs and several other libraries use this short and simple trick.
Something I just came up with:
if (item.length)
//This is an array
else
//not an array
Related
How do I check if a variable is an array in JavaScript?
if (variable.constructor == Array)
There are several ways of checking if an variable is an array or not. The best solution is the one you have chosen.
variable.constructor === Array
This is the fastest method on Chrome, and most likely all other browsers. All arrays are objects, so checking the constructor property is a fast process for JavaScript engines.
If you are having issues with finding out if an objects property is an array, you must first check if the property is there.
variable.prop && variable.prop.constructor === Array
Some other ways are:
Array.isArray(variable)
Update May 23, 2019 using Chrome 75, shout out to #AnduAndrici for having me revisit this with his question
This last one is, in my opinion the ugliest, and it is one of the slowest fastest. Running about 1/5 the speed as the first example. This guy is about 2-5% slower, but it's pretty hard to tell. Solid to use! Quite impressed by the outcome. Array.prototype, is actually an array. you can read more about it here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
variable instanceof Array
This method runs about 1/3 the speed as the first example. Still pretty solid, looks cleaner, if you're all about pretty code and not so much on performance. Note that checking for numbers does not work as variable instanceof Number always returns false. Update: instanceof now goes 2/3 the speed!
So yet another update
Object.prototype.toString.call(variable) === '[object Array]';
This guy is the slowest for trying to check for an Array. However, this is a one stop shop for any type you're looking for. However, since you're looking for an array, just use the fastest method above.
Also, I ran some test: http://jsperf.com/instanceof-array-vs-array-isarray/35 So have some fun and check it out.
Note: #EscapeNetscape has created another test as jsperf.com is down. http://jsben.ch/#/QgYAV I wanted to make sure the original link stay for whenever jsperf comes back online.
You could also use:
if (value instanceof Array) {
alert('value is Array!');
} else {
alert('Not an array');
}
This seems to me a pretty elegant solution, but to each his own.
Edit:
As of ES5 there is now also:
Array.isArray(value);
But this will break on older browsers, unless you are using polyfills (basically... IE8 or similar).
There are multiple solutions with all their own quirks. This page gives a good overview. One possible solution is:
function isArray(o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
In modern browsers (and some legacy browsers), you can do
Array.isArray(obj)
(Supported by Chrome 5, Firefox 4.0, IE 9, Opera 10.5 and Safari 5)
If you need to support older versions of IE, you can use es5-shim to polyfill Array.isArray; or 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 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
Note: the arguments keyword that can be used to access the argument of a function isn't an Array, even though it (usually) behaves like one:
var func = function() {
console.log(arguments) // [1, 2, 3]
console.log(arguments.length) // 3
console.log(Array.isArray(arguments)) // false !!!
console.log(arguments.slice) // undefined (Array.prototype methods not available)
console.log([3,4,5].slice) // function slice() { [native code] }
}
func(1, 2, 3)
I noticed someone mentioned jQuery, but I didn't know there was an isArray() function. It turns out it was added in version 1.3.
jQuery implements it as Peter suggests:
isArray: function( obj ) {
return toString.call(obj) === "[object Array]";
},
Having put a lot of faith in jQuery already (especially their techniques for cross-browser compatibility) I will either upgrade to version 1.3 and use their function (providing that upgrading doesn’t cause too many problems) or use this suggested method directly in my code.
Many thanks for the suggestions.
This is an old question but having the same problem i found a very elegant solution that i want to share.
Adding a prototype to Array makes it very simple
Array.prototype.isArray = true;
Now once if you have an object you want to test to see if its an array all you need is to check for the new property
var box = doSomething();
if (box.isArray) {
// do something
}
isArray is only available if its an array
Via Crockford:
function typeOf(value) {
var s = typeof value;
if (s === 'object') {
if (value) {
if (value instanceof Array) {
s = 'array';
}
} else {
s = 'null';
}
}
return s;
}
The main failing Crockford mentions is an inability to correctly determine arrays that were created in a different context, e.g., window.
That page has a much more sophisticated version if this is insufficient.
If you're only dealing with EcmaScript 5 and above then you can use the built in Array.isArray function
e.g.,
Array.isArray([]) // true
Array.isArray("foo") // false
Array.isArray({}) // false
I personally like Peter's suggestion: https://stackoverflow.com/a/767499/414784 (for ECMAScript 3. For ECMAScript 5, use Array.isArray())
Comments on the post indicate, however, that if toString() is changed at all, that way of checking an array will fail. If you really want to be specific and make sure toString() has not been changed, and there are no problems with the objects class attribute ([object Array] is the class attribute of an object that is an array), then I recommend doing something like this:
//see if toString returns proper class attributes of objects that are arrays
//returns -1 if it fails test
//returns true if it passes test and it's an array
//returns false if it passes test and it's not an array
function is_array(o)
{
// make sure an array has a class attribute of [object Array]
var check_class = Object.prototype.toString.call([]);
if(check_class === '[object Array]')
{
// test passed, now check
return Object.prototype.toString.call(o) === '[object Array]';
}
else
{
// may want to change return value to something more desirable
return -1;
}
}
Note that in JavaScript The Definitive Guide 6th edition, 7.10, it says Array.isArray() is implemented using Object.prototype.toString.call() in ECMAScript 5. Also note that if you're going to worry about toString()'s implementation changing, you should also worry about every other built in method changing too. Why use push()? Someone can change it! Such an approach is silly. The above check is an offered solution to those worried about toString() changing, but I believe the check is unnecessary.
When I posted this question the version of JQuery that I was using didn't include an isArray function. If it had have I would have probably just used it trusting that implementation to be the best browser independant way to perform this particular type check.
Since JQuery now does offer this function, I would always use it...
$.isArray(obj);
(as of version 1.6.2) It is still implemented using comparisons on strings in the form
toString.call(obj) === "[object Array]"
Thought I would add another option for those who might already be using the Underscore.js library in their script. Underscore.js has an isArray() function (see http://underscorejs.org/#isArray).
_.isArray(object)
Returns true if object is an Array.
If you are using Angular, you can use the angular.isArray() function
var myArray = [];
angular.isArray(myArray); // returns true
var myObj = {};
angular.isArray(myObj); //returns false
http://docs.angularjs.org/api/ng/function/angular.isArray
In Crockford's JavaScript The Good Parts, there is a function to check if the given argument is an array:
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
He explains:
First, we ask if the value is truthy. We do this to reject null and other falsy values. Second, we ask if the typeof value is 'object'. This will be true for objects, arrays, and (weirdly) null. Third, we ask if the value has a length property that is a number. This will always be true for arrays, but usually not for objects. Fourth, we ask if the value contains a splice method. This again will be true for all arrays. Finally, we ask if the length property is enumerable (will length be produced by a for in loop?). That will be false for all arrays. This is the most reliable test for arrayness that I have found. It is unfortunate that it is so complicated.
The universal solution is below:
Object.prototype.toString.call(obj)=='[object Array]'
Starting from ECMAScript 5, a formal solution is :
Array.isArray(arr)
Also, for old JavaScript libs, you can find below solution although it's not accurate enough:
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
The solutions are from http://www.pixelstech.net/topic/85-How-to-check-whether-an-object-is-an-array-or-not-in-JavaScript
For those who code-golf, an unreliable test with fewest characters:
function isArray(a) {
return a.map;
}
This is commonly used when traversing/flattening a hierarchy:
function golf(a) {
return a.map?[].concat.apply([],a.map(golf)):a;
}
input: [1,2,[3,4,[5],6],[7,[8,[9]]]]
output: [1, 2, 3, 4, 5, 6, 7, 8, 9]
code referred from https://github.com/miksago/Evan.js/blob/master/src/evan.js
var isArray = Array.isArray || function(obj) {
return !!(obj && obj.concat && obj.unshift && !obj.callee);};
I was using this line of code:
if (variable.push) {
// variable is array, since AMAIK only arrays have push() method.
}
I have created this little bit of code, which can return true types.
I am not sure about performance yet, but it's an attempt to properly identify the typeof.
https://github.com/valtido/better-typeOf also blogged a little about it here http://www.jqui.net/jquery/better-typeof-than-the-javascript-native-typeof/
it works, similar to the current typeof.
var user = [1,2,3]
typeOf(user); //[object Array]
It think it may need a bit of fine tuning, and take into account things, I have not come across or test it properly. so further improvements are welcomed, whether it's performance wise, or incorrectly re-porting of typeOf.
I think using myObj.constructor==Object and myArray.constructor==Array is the best way. Its almost 20x faster than using toString(). If you extend objects with your own constructors and want those creations to be considered "objects" as well than this doesn't work, but otherwise its way faster. typeof is just as fast as the constructor method but typeof []=='object' returns true which will often be undesirable. http://jsperf.com/constructor-vs-tostring
one thing to note is that null.constructor will throw an error so if you might be checking for null values you will have to first do if(testThing!==null){}
From w3schools:
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
I liked the Brian answer:
function is_array(o){
// make sure an array has a class attribute of [object Array]
var check_class = Object.prototype.toString.call([]);
if(check_class === '[object Array]') {
// test passed, now check
return Object.prototype.toString.call(o) === '[object Array]';
} else{
// may want to change return value to something more desirable
return -1;
}
}
but you could just do like this:
return Object.prototype.toString.call(o) === Object.prototype.toString.call([]);
I tried most of the solutions here. But none of them worked. Then I came up with a simple solution. Hope it will help someone & save their time.
if(variable.constructor != undefined && variable.constructor.length > 0) {
/// IT IS AN ARRAY
} else {
/// IT IS NOT AN ARRAY
}
Since the .length property is special for arrays in javascript you can simply say
obj.length === +obj.length // true if obj is an array
Underscorejs and several other libraries use this short and simple trick.
Something I just came up with:
if (item.length)
//This is an array
else
//not an array
How do I check if a variable is an array in JavaScript?
if (variable.constructor == Array)
There are several ways of checking if an variable is an array or not. The best solution is the one you have chosen.
variable.constructor === Array
This is the fastest method on Chrome, and most likely all other browsers. All arrays are objects, so checking the constructor property is a fast process for JavaScript engines.
If you are having issues with finding out if an objects property is an array, you must first check if the property is there.
variable.prop && variable.prop.constructor === Array
Some other ways are:
Array.isArray(variable)
Update May 23, 2019 using Chrome 75, shout out to #AnduAndrici for having me revisit this with his question
This last one is, in my opinion the ugliest, and it is one of the slowest fastest. Running about 1/5 the speed as the first example. This guy is about 2-5% slower, but it's pretty hard to tell. Solid to use! Quite impressed by the outcome. Array.prototype, is actually an array. you can read more about it here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
variable instanceof Array
This method runs about 1/3 the speed as the first example. Still pretty solid, looks cleaner, if you're all about pretty code and not so much on performance. Note that checking for numbers does not work as variable instanceof Number always returns false. Update: instanceof now goes 2/3 the speed!
So yet another update
Object.prototype.toString.call(variable) === '[object Array]';
This guy is the slowest for trying to check for an Array. However, this is a one stop shop for any type you're looking for. However, since you're looking for an array, just use the fastest method above.
Also, I ran some test: http://jsperf.com/instanceof-array-vs-array-isarray/35 So have some fun and check it out.
Note: #EscapeNetscape has created another test as jsperf.com is down. http://jsben.ch/#/QgYAV I wanted to make sure the original link stay for whenever jsperf comes back online.
You could also use:
if (value instanceof Array) {
alert('value is Array!');
} else {
alert('Not an array');
}
This seems to me a pretty elegant solution, but to each his own.
Edit:
As of ES5 there is now also:
Array.isArray(value);
But this will break on older browsers, unless you are using polyfills (basically... IE8 or similar).
There are multiple solutions with all their own quirks. This page gives a good overview. One possible solution is:
function isArray(o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
In modern browsers (and some legacy browsers), you can do
Array.isArray(obj)
(Supported by Chrome 5, Firefox 4.0, IE 9, Opera 10.5 and Safari 5)
If you need to support older versions of IE, you can use es5-shim to polyfill Array.isArray; or 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 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
Note: the arguments keyword that can be used to access the argument of a function isn't an Array, even though it (usually) behaves like one:
var func = function() {
console.log(arguments) // [1, 2, 3]
console.log(arguments.length) // 3
console.log(Array.isArray(arguments)) // false !!!
console.log(arguments.slice) // undefined (Array.prototype methods not available)
console.log([3,4,5].slice) // function slice() { [native code] }
}
func(1, 2, 3)
I noticed someone mentioned jQuery, but I didn't know there was an isArray() function. It turns out it was added in version 1.3.
jQuery implements it as Peter suggests:
isArray: function( obj ) {
return toString.call(obj) === "[object Array]";
},
Having put a lot of faith in jQuery already (especially their techniques for cross-browser compatibility) I will either upgrade to version 1.3 and use their function (providing that upgrading doesn’t cause too many problems) or use this suggested method directly in my code.
Many thanks for the suggestions.
This is an old question but having the same problem i found a very elegant solution that i want to share.
Adding a prototype to Array makes it very simple
Array.prototype.isArray = true;
Now once if you have an object you want to test to see if its an array all you need is to check for the new property
var box = doSomething();
if (box.isArray) {
// do something
}
isArray is only available if its an array
Via Crockford:
function typeOf(value) {
var s = typeof value;
if (s === 'object') {
if (value) {
if (value instanceof Array) {
s = 'array';
}
} else {
s = 'null';
}
}
return s;
}
The main failing Crockford mentions is an inability to correctly determine arrays that were created in a different context, e.g., window.
That page has a much more sophisticated version if this is insufficient.
If you're only dealing with EcmaScript 5 and above then you can use the built in Array.isArray function
e.g.,
Array.isArray([]) // true
Array.isArray("foo") // false
Array.isArray({}) // false
I personally like Peter's suggestion: https://stackoverflow.com/a/767499/414784 (for ECMAScript 3. For ECMAScript 5, use Array.isArray())
Comments on the post indicate, however, that if toString() is changed at all, that way of checking an array will fail. If you really want to be specific and make sure toString() has not been changed, and there are no problems with the objects class attribute ([object Array] is the class attribute of an object that is an array), then I recommend doing something like this:
//see if toString returns proper class attributes of objects that are arrays
//returns -1 if it fails test
//returns true if it passes test and it's an array
//returns false if it passes test and it's not an array
function is_array(o)
{
// make sure an array has a class attribute of [object Array]
var check_class = Object.prototype.toString.call([]);
if(check_class === '[object Array]')
{
// test passed, now check
return Object.prototype.toString.call(o) === '[object Array]';
}
else
{
// may want to change return value to something more desirable
return -1;
}
}
Note that in JavaScript The Definitive Guide 6th edition, 7.10, it says Array.isArray() is implemented using Object.prototype.toString.call() in ECMAScript 5. Also note that if you're going to worry about toString()'s implementation changing, you should also worry about every other built in method changing too. Why use push()? Someone can change it! Such an approach is silly. The above check is an offered solution to those worried about toString() changing, but I believe the check is unnecessary.
When I posted this question the version of JQuery that I was using didn't include an isArray function. If it had have I would have probably just used it trusting that implementation to be the best browser independant way to perform this particular type check.
Since JQuery now does offer this function, I would always use it...
$.isArray(obj);
(as of version 1.6.2) It is still implemented using comparisons on strings in the form
toString.call(obj) === "[object Array]"
Thought I would add another option for those who might already be using the Underscore.js library in their script. Underscore.js has an isArray() function (see http://underscorejs.org/#isArray).
_.isArray(object)
Returns true if object is an Array.
If you are using Angular, you can use the angular.isArray() function
var myArray = [];
angular.isArray(myArray); // returns true
var myObj = {};
angular.isArray(myObj); //returns false
http://docs.angularjs.org/api/ng/function/angular.isArray
In Crockford's JavaScript The Good Parts, there is a function to check if the given argument is an array:
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
He explains:
First, we ask if the value is truthy. We do this to reject null and other falsy values. Second, we ask if the typeof value is 'object'. This will be true for objects, arrays, and (weirdly) null. Third, we ask if the value has a length property that is a number. This will always be true for arrays, but usually not for objects. Fourth, we ask if the value contains a splice method. This again will be true for all arrays. Finally, we ask if the length property is enumerable (will length be produced by a for in loop?). That will be false for all arrays. This is the most reliable test for arrayness that I have found. It is unfortunate that it is so complicated.
The universal solution is below:
Object.prototype.toString.call(obj)=='[object Array]'
Starting from ECMAScript 5, a formal solution is :
Array.isArray(arr)
Also, for old JavaScript libs, you can find below solution although it's not accurate enough:
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
The solutions are from http://www.pixelstech.net/topic/85-How-to-check-whether-an-object-is-an-array-or-not-in-JavaScript
For those who code-golf, an unreliable test with fewest characters:
function isArray(a) {
return a.map;
}
This is commonly used when traversing/flattening a hierarchy:
function golf(a) {
return a.map?[].concat.apply([],a.map(golf)):a;
}
input: [1,2,[3,4,[5],6],[7,[8,[9]]]]
output: [1, 2, 3, 4, 5, 6, 7, 8, 9]
code referred from https://github.com/miksago/Evan.js/blob/master/src/evan.js
var isArray = Array.isArray || function(obj) {
return !!(obj && obj.concat && obj.unshift && !obj.callee);};
I was using this line of code:
if (variable.push) {
// variable is array, since AMAIK only arrays have push() method.
}
I have created this little bit of code, which can return true types.
I am not sure about performance yet, but it's an attempt to properly identify the typeof.
https://github.com/valtido/better-typeOf also blogged a little about it here http://www.jqui.net/jquery/better-typeof-than-the-javascript-native-typeof/
it works, similar to the current typeof.
var user = [1,2,3]
typeOf(user); //[object Array]
It think it may need a bit of fine tuning, and take into account things, I have not come across or test it properly. so further improvements are welcomed, whether it's performance wise, or incorrectly re-porting of typeOf.
I think using myObj.constructor==Object and myArray.constructor==Array is the best way. Its almost 20x faster than using toString(). If you extend objects with your own constructors and want those creations to be considered "objects" as well than this doesn't work, but otherwise its way faster. typeof is just as fast as the constructor method but typeof []=='object' returns true which will often be undesirable. http://jsperf.com/constructor-vs-tostring
one thing to note is that null.constructor will throw an error so if you might be checking for null values you will have to first do if(testThing!==null){}
From w3schools:
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
I liked the Brian answer:
function is_array(o){
// make sure an array has a class attribute of [object Array]
var check_class = Object.prototype.toString.call([]);
if(check_class === '[object Array]') {
// test passed, now check
return Object.prototype.toString.call(o) === '[object Array]';
} else{
// may want to change return value to something more desirable
return -1;
}
}
but you could just do like this:
return Object.prototype.toString.call(o) === Object.prototype.toString.call([]);
I tried most of the solutions here. But none of them worked. Then I came up with a simple solution. Hope it will help someone & save their time.
if(variable.constructor != undefined && variable.constructor.length > 0) {
/// IT IS AN ARRAY
} else {
/// IT IS NOT AN ARRAY
}
Since the .length property is special for arrays in javascript you can simply say
obj.length === +obj.length // true if obj is an array
Underscorejs and several other libraries use this short and simple trick.
Something I just came up with:
if (item.length)
//This is an array
else
//not an array
I'm trying to figure out what's gone wrong with my json serializing, have the current version of my app with and old one and am finding some surprising differences in the way JSON.stringify() works (Using the JSON library from json.org).
In the old version of my app:
JSON.stringify({"a":[1,2]})
gives me this;
"{\"a\":[1,2]}"
in the new version,
JSON.stringify({"a":[1,2]})
gives me this;
"{\"a\":\"[1, 2]\"}"
any idea what could have changed to make the same library put quotes around the array brackets in the new version?
Since JSON.stringify has been shipping with some browsers lately, I would suggest using it instead of Prototype’s toJSON. You would then check for window.JSON && window.JSON.stringify and only include the json.org library otherwise (via document.createElement('script')…). To resolve the incompatibilities, use:
if(window.Prototype) {
delete Object.prototype.toJSON;
delete Array.prototype.toJSON;
delete Hash.prototype.toJSON;
delete String.prototype.toJSON;
}
The function JSON.stringify() defined in ECMAScript 5 and above (Page 201 - the JSON Object, pseudo-code Page 205), uses the function toJSON() when available on objects.
Because Prototype.js (or another library that you are using) defines an Array.prototype.toJSON() function, arrays are first converted to strings using Array.prototype.toJSON() then string quoted by JSON.stringify(), hence the incorrect extra quotes around the arrays.
The solution is therefore straight-forward and trivial (this is a simplified version of Raphael Schweikert's answer):
delete Array.prototype.toJSON
This produces of course side effects on libraries that rely on a toJSON() function property for arrays. But I find this a minor inconvenience considering the incompatibility with ECMAScript 5.
It must be noted that the JSON Object defined in ECMAScript 5 is efficiently implemented in modern browsers and therefore the best solution is to conform to the standard and modify existing libraries.
A possible solution which will not affect other Prototype dependencies would be:
var _json_stringify = JSON.stringify;
JSON.stringify = function(value) {
var _array_tojson = Array.prototype.toJSON;
delete Array.prototype.toJSON;
var r=_json_stringify(value);
Array.prototype.toJSON = _array_tojson;
return r;
};
This takes care of the Array toJSON incompatibility with JSON.stringify and also retains toJSON functionality as other Prototype libraries may depend on it.
Edit to make a bit more accurate:
The problem key bit of code is in the JSON library from JSON.org (and other implementations of ECMAScript 5's JSON object):
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
The problem is that the Prototype library extends Array to include a toJSON method, which the JSON object will call in the code above. When the JSON object hits the array value it calls toJSON on the array which is defined in Prototype, and that method returns a string version of the array. Hence, the quotes around the array brackets.
If you delete toJSON from the Array object the JSON library should work properly. Or, just use the JSON library.
I think a better solution would be to include this just after prototype has been loaded
JSON = JSON || {};
JSON.stringify = function(value) { return value.toJSON(); };
JSON.parse = JSON.parse || function(jsonsring) { return jsonsring.evalJSON(true); };
This makes the prototype function available as the standard JSON.stringify() and JSON.parse(), but keeps the native JSON.parse() if it is available, so this makes things more compatible with older browsers.
I'm not that fluent with Prototype, but I saw this in its docs:
Object.toJSON({"a":[1,2]})
I'm not sure if this would have the same problem the current encoding has, though.
There's also a longer tutorial about using JSON with Prototype.
This is the code I used for the same issue:
function stringify(object){
var Prototype = window.Prototype
if (Prototype && Prototype.Version < '1.7' &&
Array.prototype.toJSON && Object.toJSON){
return Object.toJSON(object)
}
return JSON.stringify(object)
}
You check if Prototype exists, then you check the version. If old version use Object.toJSON (if is defined) in all other cases fallback to JSON.stringify()
Here's how I'm dealing with it.
var methodCallString = Object.toJSON? Object.toJSON(options.jsonMethodCall) : JSON.stringify(options.jsonMethodCall);
My tolerant solution checks whether Array.prototype.toJSON is harmful for JSON stringify and keeps it when possible to let the surrounding code work as expected:
var dummy = { data: [{hello: 'world'}] }, test = {};
if(Array.prototype.toJSON) {
try {
test = JSON.parse(JSON.stringify(dummy));
if(!test || dummy.data !== test.data) {
delete Array.prototype.toJSON;
}
} catch(e) {
// there only hope
}
}
As people have pointed out, this is due to Prototype.js - specifically versions prior to 1.7. I had a similar situation but had to have code that operated whether Prototype.js was there or not; this means I can't just delete the Array.prototype.toJSON as I'm not sure what relies on it. For that situation this is the best solution I came up with:
function safeToJSON(item){
if ([1,2,3] === JSON.parse(JSON.stringify([1,2,3]))){
return JSON.stringify(item); //sane behavior
} else {
return item.toJSON(); // Prototype.js nonsense
}
}
Hopefully it will help someone.
If you don't want to kill everything, and have a code that would be okay on most browsers, you could do it this way :
(function (undefined) { // This is just to limit _json_stringify to this scope and to redefine undefined in case it was
if (true ||typeof (Prototype) !== 'undefined') {
// First, ensure we can access the prototype of an object.
// See http://stackoverflow.com/questions/7662147/how-to-access-object-prototype-in-javascript
if(typeof (Object.getPrototypeOf) === 'undefined') {
if(({}).__proto__ === Object.prototype && ([]).__proto__ === Array.prototype) {
Object.getPrototypeOf = function getPrototypeOf (object) {
return object.__proto__;
};
} else {
Object.getPrototypeOf = function getPrototypeOf (object) {
// May break if the constructor has been changed or removed
return object.constructor ? object.constructor.prototype : undefined;
}
}
}
var _json_stringify = JSON.stringify; // We save the actual JSON.stringify
JSON.stringify = function stringify (obj) {
var obj_prototype = Object.getPrototypeOf(obj),
old_json = obj_prototype.toJSON, // We save the toJSON of the object
res = null;
if (old_json) { // If toJSON exists on the object
obj_prototype.toJSON = undefined;
}
res = _json_stringify.apply(this, arguments);
if (old_json)
obj_prototype.toJSON = old_json;
return res;
};
}
}.call(this));
This seems complex, but this is complex only to handle most use cases.
The main idea is overriding JSON.stringify to remove toJSON from the object passed as an argument, then call the old JSON.stringify, and finally restore it.
I just brushing up on AngularJS and I came across angular.isDefined and angular.isUndefined, why would you use these? Why not just do
if (!obj) or if (obj === undefined)
I get why you might not want not want to do !var because you'll get other falsey obj as well as undefined. But why bother creating a method to take care of this?
In older browsers the undefined constant is not a constant, so you can break it by accidentally assigning a value to it:
if (undefined = obj) // oops, now undefined isn't undefined any more...
The method to check for undefined values that is safe from the non-constant undefined is a bit lengthier and is to check the type:
if (typeof obj === "undefined")
Library methods like isUndefined uses this safe method, so it allows you to write code that is compatible with more browsers without having to know every quirk of every version of every browser.
the two are not same: consider var obj = false, then if (!obj) would be truthy but if (obj === undefined) would be falsy
I am utterly confused. I know this has been asked a million times. And I have looked at questions like:
Test if something is not undefined in JavaScript
Now the problem is when doing the check I have found multiple things you can do.
I need to check if an object is an array, to do that I check if the "length" property is there. Now what one would I use?
if (obj.length)
or
if (obj.length === undefined)
or
if (typeof obj.length === "undefined")
or
if (obj.length == null)
or something else?
I understand that === doesn't do any type conversion, and the if statement is just wanting a "truthy" or "falsey" value, meaning obj.length will return false if the length is 0, but that's not what we want. We want to now if it is defined. Which is why I go to type test. But which way is the best?
Here are some tests I did. 2, 3 and 4 work.
Sorry for the stuff in between. I was doing it in the console for this page.
Short answer:
if (obj instanceof Array) {
// obj is an array
}
Or, if you don't know whether obj is defined or not:
if ((typeof obj !== "undefined") && (obj instanceof Array)) {
// obj is an array
}
To discuss why yours aren't quite right:
obj.anyProperty will throw a ReferenceError if obj is undefined. This affects all four of the things you put.
if (obj.length) will evaluate to false for an empty array, which isn't what you want. Because the length is 0 (a falsy value), it will falsely be inaccurate. This could also have issues if another object has a length property.
if (obj.length === undefined) will usually work, but it's frowned upon because undefined can be redefined. Someone could break your code by writing undefined = obj.length. This can also create false negatives; obj could happen to have a property called "length" and it would falsely call it an array.
if (typeof obj.length === "undefined") works fine, but could detect the same false negatives as the above.
if (obj.length == null) will work okay, but has the same bugs as above. In a double-equals (==), it matches null and undefined.
I would do `
obj instanceof Array
to check if obj is an array
http://jsfiddle.net/Tcjk4/
For what it's worth, here's how jQuery checks whether something is an array:
isArray: Array.isArray || function( obj ) {
return jQuery.type(obj) === "array";
},
This uses ES5's Array.isArray if available, or a custom check in older browsers. jQuery makes this function accessible as $.isArray.
jQuery.type is basically an enhanced typeof that works around some limitations of the JavaScript language and browser bugs. Whereas typeof returns 'object' for anything object-like ({}, [], even null), $.type returns the internal JavaScript [[Class]] property of the object.
In fact, this method of determining type is actually safer than instanceof:
Both instanceof and constructor look very innocent and seem like great
ways to check if an object is an array.
The problems arise when it comes to scripting in multi-frame DOM
environments. In a nutshell, Array objects created within one iframe
do not share [[Prototype]]s with arrays created within another
iframe. Their constructors are different objects and so both
instanceof and constructor checks fail:
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // [1,2,3]
// Boom!
arr instanceof Array; // false
// Boom!
arr.constructor === Array; // false
More comment than answer.
While a test like object instanceof Array will work in most cases (it may fail where frames or inter–window communication are involved), it's a good idea to consider what you really need to test for and design the test accordingly. Testing explicitly whether an object is an array or not is almost always unnecessary.
In this case, it seems that you just want to use the length property for iterating over the object's numeric properties.
If that's the case, all you need to do is read the value of the length property and use it. Whether the property is missing, or hasn't been assigned a value, or has a value of undefined or 0, you don't want to do the loop. Fortunately, you can do all of those tests in one go (and also skip processing if the value is Null or '', which seems sensible too):
if (obj.length) {
// iterate over numeric properties of obj
}
That will make the method generic, so it can be applied to any Object that has a suitable length property and some numeric properties (e.g. a jQuery object or an HTMLCollection object).
If you need some other feature of an array (say push or slice), you can also test for those.
If you are using the test as a logic fork (e.g. if it's an array do one thing, if it's a plain object do something else) then you should consider whether that's a sensible thing to do.
var sizeArrayOrObject = function(obj) {
var size = 0, key;
for (key in obj) {
if (typeof obj.key === 'undefined') size++;
}
return size;
};
sizeArrayOrObject([]); // 0
sizeArrayOrObject([5,6]); // 2
sizeArrayOrObject({}); // 0
sizeArrayOrObject({id:8}); // 1
to use underscore.js http://underscorejs.org/#isObject
_.isArray(object)
Returns true if object is an Array.
(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true
_.isObject(value)
Returns true if value is an Object. Note that JavaScript arrays and functions are objects, while (normal) strings and numbers are not.
_.isObject({});
=> true
_.isObject(1);
=> false