How Lodash isArrayLike Safely Validates Strings
Lodash’s _.isArrayLike utility evaluates whether a value
has an indexed collection format without throwing runtime exceptions,
treating strings as valid array-like targets. This article details the
internal mechanics of _.isArrayLike, demonstrating how it
safely interacts with primitive strings and String wrapper
objects by combining null-checks, JavaScript's autoboxing behavior,
strict numeric range validation, and function exclusion guards.
The Underlying
Implementation of _.isArrayLike
In the Lodash source code, _.isArrayLike is defined with
a concise implementation:
function isArrayLike(value) {
return value != null && typeof value !== 'function' && isLength(value.length);
}When a string instance is passed into this function, each component of the expression works sequentially to ensure safety and correctness.
Guarding Against Nullish Values
The initial condition value != null performs a loose
inequality check. This filters out both null and
undefined in a single comparison. If this guard were
omitted, attempting to read value.length on a nullish input
would immediately cause the JavaScript engine to throw a
TypeError: Cannot read properties of undefined (reading 'length').
By evaluating this first, Lodash prevents unhandled exceptions prior to
property inspection.
Safe Property Access via Autoboxing
In JavaScript, string primitives (e.g., 'hello') are not
objects, but reading .length on a string primitive does not
throw an error. The runtime uses a mechanism called autoboxing, which
temporarily wraps the primitive in an internal String
object to access its properties.
Because JavaScript strings inherently possess an immutable,
non-negative integer .length property reflecting their
UTF-16 code unit count, accessing .length returns a valid
number. For explicit String object instances created via
new String('hello'), the property access behaves as
standard object property lookup. In both scenarios, property retrieval
succeeds without throwing exceptions.
Validating the
Length Property with isLength
Even if an entity contains a .length property, it might
not be a valid collection length. Lodash delegates the validation of
this property to the internal isLength helper:
var MAX_SAFE_INTEGER = 9007199254740991;
function isLength(value) {
return typeof value === 'number' &&
value > -1 && value % 1 === 0 && value <= MAX_SAFE_INTEGER;
}For string instances, isLength(value.length) ensures
that:
- The
lengthvalue is strictly a primitive number (typeof value === 'number'). - The value is non-negative (
value > -1). - The value is an integer rather than a floating-point number
(
value % 1 === 0). - The value does not exceed JavaScript's safe integer threshold
(
value <= MAX_SAFE_INTEGER).
Because a string's .length is always a non-negative
integer within standard memory limits, strings consistently satisfy all
criteria defined in isLength.
Eliminating Function False Positives
JavaScript functions also possess a .length property,
which represents the function's arity (the number of formal parameters).
Despite having a valid numerical length, functions are not intended to
be processed as collections.
The condition typeof value !== 'function' explicitly
excludes functions before checking isLength. Since strings
have a typeof value of 'string' (or
'object' when using the String constructor),
they safely pass this exclusion check.