How Lodash indexOf Handles Zero with Strict Equality
This article examines how the _.indexOf method in the
Lodash JavaScript library evaluates zero values, detailing the mechanics
of JavaScript's number representation, strict equality comparison, and
the internal implementation of index searches. Readers will learn why
strict equality does not distinguish between integer zero and
floating-point zero, how positive and negative zeros are evaluated, and
how Lodash executes these comparisons under the hood.
Number Representation in JavaScript
In JavaScript, all numbers are represented as double-precision 64-bit
binary format IEEE 754 values. The language engine does not provide
distinct primitive data types for integers versus floating-point
numbers. Consequently, an integer literal zero (0) and a
floating-point literal zero (0.0) translate to the exact
same underlying binary representation in memory:
0 === 0.0; // trueBecause both representations are identical at the engine level,
JavaScript does not treat integer zero and floating zero as separate
states. The only standard distinction IEEE 754 provides regarding zero
values is sign: positive zero (+0) and negative zero
(-0).
The Strict Equality Comparison
(===)
Lodash's _.indexOf method relies on the Strict Equality
Comparison algorithm defined by ECMAScript specifications. When using
===, the algorithm evaluates numbers according to specific
rules:
- If either operand is
NaN, the result isfalse. - If the values are identical numbers, the result is
true. - If one value is
+0and the other is-0, the result istrue.
Because === explicitly evaluates +0 === -0
as true and considers 0 and 0.0
identical, strict equality actively prevents differentiation between
these representations rather than separating them.
Lodash's Internal
Implementation of _.indexOf
When calling _.indexOf(array, value, fromIndex), Lodash
delegates the operation to internal helper functions:
baseIndexOf: Determines whether the search target requires special handling (such asNaN, which cannot match itself using strict equality).strictIndexOf: Executes when searching for regular primitive values, including numbers.
The internal implementation of strictIndexOf runs a
optimized while loop that directly uses the strict equality
operator:
function strictIndexOf(array, value, fromIndex) {
let index = fromIndex - 1;
const { length } = array;
while (++index < length) {
if (array[index] === value) {
return index;
}
}
return -1;
}Because array[index] === value is the evaluation
condition, passing 0, 0.0, +0, or
-0 matches the first occurrence of any zero representation
found in the array:
const array = [1, 0, 2];
_.indexOf(array, 0.0); // Returns 1
_.indexOf(array, -0); // Returns 1Distinguishing Zeroes Beyond Strict Equality
Because _.indexOf adheres to strict equality semantics,
it mirrors the behavior of native Array.prototype.indexOf.
If an application requires distinguishing signed zeros (+0
versus -0), strict equality cannot be used. Instead,
differentiation requires the SameValue algorithm implemented via
Object.is() or division by zero (since
1 / 0 === Infinity while
1 / -0 === -Infinity). Lodash intentionally avoids this
differentiation in _.indexOf to remain consistent with
standard JavaScript array search conventions.