How Lodash _.isArray Enables Cross-Environment Checks
This article explores how the Lodash utility function
_.isArray reliably identifies arrays across distinct
JavaScript execution environments. You will learn the limitations of
traditional type-checking mechanisms, such as instanceof,
why cross-realm contexts like iframes cause standard checks to fail, and
how Lodash implements native features and fallback methods to ensure
consistent, fail-safe array detection.
The Limitation of
instanceof Array
The most common native approach to check if an object is an array is
using the instanceof operator:
value instanceof ArrayWhile this works within a single execution context, it fails in cross-realm environments. A realm represents an execution context with its own global environment and built-in objects. Examples of multiple realms include:
- Web pages containing
<iframe>elements - Node.js scripts running code inside
vmcontexts - Browser extensions interacting with host pages
Each realm has its own distinct global object and its own native
Array constructor. If an array is initialized inside an
iframe and passed to the parent window, evaluating
iframeArray instanceof Array inside the parent window
returns false. This happens because
iframeArray inherits from the iframe’s
Array.prototype, not the parent window's
Array.prototype.
Native Delegation:
Array.isArray
To resolve the realm issue, ECMAScript 5.1 introduced
Array.isArray(). This method checks the internal
characteristics of an object rather than its prototype chain, making it
natively realm-agnostic.
Under the hood, Lodash's _.isArray first attempts to
delegate directly to the native Array.isArray method:
const nativeIsArray = Array.isArray;If the running JavaScript engine provides Array.isArray,
Lodash utilizes it directly for optimal performance and built-in
cross-realm reliability.
The Fallback
Mechanism: Object.prototype.toString
In environments where native Array.isArray is
unavailable or altered, Lodash falls back on the standard
Object.prototype.toString technique:
function isArray(value) {
return value != null &&
typeof value == 'object' &&
Object.prototype.toString.call(value) == '[object Array]';
}Every built-in JavaScript object has an internal
[[Class]] property (or in modern specifications, an
internal slot associated with Symbol.toStringTag). When
Object.prototype.toString.call(value) is invoked:
- The runtime accesses the target object's internal type designation.
- It returns a string in the format
[object Type]. - For any native array created in any realm, the returned value is
always
"[object Array]".
Because this check evaluates a primitive string rather than object
references in memory, it completely bypasses identity checks between
different Array constructors. Whether an array originates
from a different frame, window, or virtual context, the string tag
remains identical.
Guarding Against Edge Cases
Beyond realm differences, _.isArray guards against
several JavaScript type anomalies:
- Null and Undefined: It verifies that the passed
value is neither
nullnorundefinedbefore performing operations, preventing runtime errors. - Array-Like Objects: Objects such as the
argumentsobject, NodeLists, or custom objects with alengthproperty are identified as objects, but their internal tag is not[object Array]._.isArraycorrectly evaluates them asfalse. - Tampered Prototypes: Modifying an object's
prototype chain with
Object.setPrototypeOfdoes not alter its internal array representation, allowing_.isArrayto maintain accurate detection.
Through native delegation combined with internal tag inspection,
_.isArray guarantees accurate array detection regardless of
the JavaScript environment, realm, or runtime variation.