Checking For Undefined
Solution 1:
Short answer:
if (obj instanceofArray) {
// obj is an array
}
Or, if you don't know whether obj
is defined or not:
if ((typeof obj !== "undefined") && (obj instanceofArray)) {
// 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
.
Solution 2:
Solution 3:
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
andconstructor
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 bothinstanceof
andconstructor
checks fail:
var iframe = document.createElement('iframe'); document.body.appendChild(iframe); xArray = window.frames[window.frames.length-1].Array; var arr = newxArray(1,2,3); // [1,2,3] // Boom! arr instanceofArray; // false // Boom! arr.constructor === Array; // false
Solution 4:
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.
Solution 5:
var sizeArrayOrObject = function(obj) {
var size = 0, key;
for (key in obj) {
if (typeof obj.key === 'undefined') size++;
}
return size;
};
sizeArrayOrObject([]); // 0sizeArrayOrObject([5,6]); // 2sizeArrayOrObject({}); // 0sizeArrayOrObject({id:8}); // 1
Post a Comment for "Checking For Undefined"