Lodash _.every on Uninitialized Array Slots
When evaluating an array composed entirely of uninitialized slots (a
sparse array such as new Array(3)), Lodash's
_.every method returns false by default. This
outcome often surprises developers because native JavaScript methods
handle sparse arrays differently. This guide explains why
_.every yields false, how it treats empty
array slots compared to native JavaScript, and how custom predicate
functions alter the result.
The Default Return Value:
false
When you pass an array with purely uninitialized slots to
_.every without a custom predicate, Lodash uses its default
iteratee, _.identity. The call evaluates to
false:
const sparseArray = new Array(3); // [ <3 empty items> ]
_.every(sparseArray);
// => falseWhy Lodash Returns
false
Lodash processes arrays using a standard index-based loop over the
array's length property rather than checking if an index
exists on the object.
- Accessing Missing Indices: In JavaScript,
attempting to access an empty or uninitialized slot via bracket notation
(e.g.,
sparseArray[0]) does not throw an error; it evaluates toundefined. - Default Iteratee (
_.identity): When no predicate is provided, Lodash defaults to_.identity, which returns the value of the current element. - Falsy Check: Lodash evaluates the first slot,
encounters
undefined, and checks its truthiness. Becauseundefinedis falsy, the condition fails immediately, causing_.everyto short-circuit and returnfalse.
Difference
Between Lodash and Native Array.prototype.every
The behavior of _.every directly contrasts with
ECMAScript's native Array.prototype.every.
Native array iteration methods check whether each index actually
exists in the array using the internal HasProperty check.
Because uninitialized slots have no assigned index property, the native
method skips them entirely:
const sparseArray = new Array(3);
// Native JavaScript
sparseArray.every(() => false);
// => trueIn native JavaScript, the callback function is never executed because
there are no initialized slots to visit. Under the rules of vacuous
truth, native Array.prototype.every returns
true. Lodash does not skip these slots, treating each empty
position as an existing element with the value
undefined.
The Impact of Custom Predicates
If you supply a custom predicate function to _.every,
the return value depends entirely on how your predicate handles
undefined.
If the predicate considers undefined to be valid,
_.every returns true:
const sparseArray = new Array(3);
// Explicitly checking for undefined
_.every(sparseArray, (value) => value === undefined);
// => true
// Predicate that always returns true
_.every(sparseArray, () => true);
// => trueIf the predicate expects defined, truthy, or specific non-undefined
values, it returns false:
// Checking for a specific data type
_.every(sparseArray, _.isNumber);
// => false