
How to Check if a Variable is an Array in JavaScript: isArray vs typeof
When developing JavaScript applications, checking data types at runtime is essential for avoiding execution errors. If a function expects an array (e.g., to loop through users using .map()) but receives a plain object or a string, the program will crash with: TypeError: x.map is not a function.
However, using JavaScript's native type checker, typeof, fails when analyzing arrays.
In this guide, we will analyze why typeof groups arrays with objects, explore the standard Array.isArray() method, and inspect cross-context iframe checks using toString.
Why typeof Fails for Arrays
In JavaScript, there are primitive data types (like string, number, boolean, null, undefined, symbol, and bigint) and reference types (objects).
In the language's core design, arrays are not a distinct data type. They are specialized objects that use numeric keys and contain a built-in .length property.
Because of this, invoking the typeof operator on an array yields:
const fruits = ['Apple', 'Banana'];
console.log(typeof fruits); // Outputs: "object"Since typeof {} also returns "object", you cannot use it to differentiate a list from a standard JSON key-value store.
Solution 1: Use Array.isArray() (Recommended)
To address this issue, the ECMAScript 5 specification introduced a dedicated method: Array.isArray().
This method checks the internal structural type of the object directly and returns a boolean value:
console.log(Array.isArray(['A', 'B'])); // true
console.log(Array.isArray({ name: 'Alex' })); // false
console.log(Array.isArray("not an array")); // false
console.log(Array.isArray(null)); // falseThis is the standard, cleanest, and most performant way to check for arrays in modern JavaScript.
Solution 2: The Cross-Context Workaround (Object.prototype.toString)
In complex web applications containing embedded iframe structures, multiple global execution contexts exist.
Each iframe has its own global execution context and its own Array constructor. If you pass an array from iframeA to the host windowB, checking it using instanceof Array will return false because the array's prototype belongs to a different frame's constructor.
To bypass this frame boundary barrier, inspect the object's internal [[Class]] property using Object.prototype.toString:
const fruits = ['Apple', 'Banana'];
const result = Object.prototype.toString.call(fruits);
console.log(result); // Outputs: "[object Array]"You can wrap this in a helper function:
function isArraySecure(value) {
return Object.prototype.toString.call(value) === '[object Array]';
}This method is highly robust and is used under the hood by older utility libraries (like lodash) to guarantee security across iframe boundaries.
Solution 3: The instanceof Operator (Local Scope Only)
You can also use the instanceof operator to check if an object's prototype chain references the Array constructor:
const colors = ['Red', 'Green'];
console.log(colors instanceof Array); // true- Warning: Avoid this method if your application communicates across multiple windows or iframes. As mentioned above, prototype comparison fails when objects cross iframe boundaries.
Array Check Methods Summary
| Method | Syntax | Safe Across Iframes? | Performance |
typeof | typeof var | N/A (returns "object") | High |
Array.isArray() | Array.isArray(var) | Yes | Highest |
Object.prototype.toString | Object.prototype.toString.call(var) | Yes | Medium |
instanceof | var instanceof Array | No | High |
Conclusion
Distinguishing arrays from standard objects in JavaScript is critical for data safety. Avoid using typeof since it registers arrays as generic objects, default to the standard Array.isArray() method for clean and highly optimized checks, and implement the Object.prototype.toString.call() fallback strategy when writing libraries that cross iframe window scopes.