Checking 'Is This an Array?' in JS
Array.isArray, instanceof, and Object.prototype.toString.call, and where each one breaks.
~/posts/is-array $ cat post.md
Overview
There are several ways to ask “is this an array?”. When I’m writing
TypeScript I default to value instanceof Array — articles say it’s
reliable because it walks the prototype chain looking for Array.
That holds up under Node, but the browser exposes a few cases where it
returns the wrong answer.
Here’s a run-through of the usual options and where each one cracks.
Trust the C++
The most robust check is V8’s Value->IsArray():
- Node and the browser both surface it as
Array.isArray(value)— it inspects the actual in-engine type instead of walking JS-level prototypes. - Fastest, most stable, most portable.
- The only limit is browsers older than ES5, which don’t have it.
Educated guesses
The other methods work most of the time but have rough edges.
value instanceof Array;
instanceof and value.constructor === Array are mechanically
similar — both compare against a single Array reference. Two
gotchas:
- A side-effect-laden library might rebind
Arrayto a different class. - In a browser, a service worker or an iframe lives in its own realm
with its own
Array. A value crossing the boundary won’t beinstanceofthe outer realm’sArray.
Object.prototype.toString.call(value) === "[object Array]";
Works in most cases. The exception is “array-likes” — iterable
non-arrays such as arguments, NodeList, or anything with a custom
Symbol.iterator. For those, this returns "[object Object]".
In practice
The short answer:
- If
Array.isArrayis available, use it. It correctly returnstruefor arrays from other realms (iframes, workers);instanceofdoes not. - For pre-ES5 environments, fall back to
Object.prototype.toString.call, with an explicitSymbol.iteratorcheck if array-likes are something you care about. instanceof Arrayis fine only inside a self-contained scope where you controlArrayand nothing crosses realms.