Javascript always has some surprises in store. for example, typeof [] return object and not array.
Non ? Si ! Oh !!!!
This has historical reasons. But this can be very confusing
How can you then properly check if something is an array?
Constructor
For example, you could check if the constructor is an array.
([]).constructor === Array // true (new Array).constructor === Array // true ({}).constructor === Array // false (true).constructor === Array // false (null).constructor === Array // TypeError (undefined).constructor === Array // TypeError As you can see this has a problem. With null and undefined a TypeError is thrown.
You could catch this for example with a try/catch.
try { (undefined).constructor === Array // true } catch(e) { } But you don't want that.
Exotic
There is also this exotic possibility to check if it is an array. You can missuse the toString() method for this.
Object.prototype.toString.call([]).indexOf('Array')!==-1 // => true Object.prototype.toString.call({}).indexOf('Array')!==-1 // => false Object.prototype.toString.call("").indexOf('Array')!==-1 // => false Object.prototype.toString.call(null).indexOf('Array')!==-1 // => false Object.prototype.toString.call(true).indexOf('Array')!==-1 // => false Object.prototype.toString.call(undefined).indexOf('Array')!==-1 // => false But it doesn't just look awkward, it is awkward.
instanceOf
Alternatively, the instanceof operator, which is also known from other languages, can of course be used here.
[] instanceof Array // => true {} instanceof Array // => false "" instanceof Array // => false null instanceof Array // => false true instanceof Array // => false 10 instanceof Array // => false undefined instanceof Array // => false Already looks pretty good. But there is also a problem here.
All these checks work only if the array was created by the original array constructor in the current environment.
const iframe = document.createElement('iframe'); document.body.appendChild(iframe); const iframeArray = window.frames[window.frames.length-1].Array; const array = new iframeArray(1,2,3); Here the two array instances do not match.
array instanceof Array; // false But there is a real solution.
Array.isArray
For these reasons, since ECMAScript 5 there is a method Array.isArray().
This also works with different instances.
Array.isArray([]) // => true Array.isArray(Array.prototype) // => surprise; true Array.isArray({}) // => false Array.isArray("") // => false Array.isArray(null) // => false Array.isArray(true) // => false Array.isArray(undefined) // => false If it (isArray) is supported, it is the solution!
hope you enjoy it!
Top comments (2)
Yes, 'Array.isArray' is the right choice.
but not only for the sake if convenience. I heared in some podcast, it is about workers and iframes. While Arrays in each frame or worker are a class from the same code, at each runtime they are a "new class". with 'isArray' it works, even dough an array was taken from a other related js scope.
Yes you are right. I try to express that with my iframe example above.