What Comparison Algorithm Does Lodash indexOf Use?
This article provides a quick overview of the comparison algorithm
used by the _.indexOf method in the Lodash JavaScript
library. It explains the SameValueZero equality algorithm,
how Lodash implements it internally, and how its behavior compares
directly to native JavaScript comparison mechanisms such as the strict
equality operator and Array.prototype.indexOf.
The Comparison Algorithm: SameValueZero
Lodash’s _.indexOf method relies on the
SameValueZero comparison algorithm to determine whether
a target value exists within an array.
The ECMAScript specification defines SameValueZero as an
equality comparison that behaves almost identically to the strict
equality operator (===), with one critical distinction: how
it treats NaN (Not-a-Number). Under
SameValueZero, NaN is considered equal to
NaN.
Rules of SameValueZero
When comparing two values, x and y,
SameValueZero(x, y) evaluates according to the following
rules:
- If
Type(x)is different fromType(y), returnfalse. - If
xisNaNandyisNaN, returntrue. - If
xis+0andyis-0(or vice versa), returntrue. - Otherwise, return the result of
x === y.
Lodash indexOf vs. Native Array.prototype.indexOf
The native JavaScript Array.prototype.indexOf method
uses the Strict Equality Comparison algorithm
(===). Because NaN === NaN evaluates to
false in standard JavaScript, native indexOf
cannot locate NaN inside an array.
// Native JavaScript behavior:
const arr = [1, NaN, 3];
arr.indexOf(NaN);
// => -1 (unable to locate NaN)
// Lodash _.indexOf behavior:
_.indexOf(arr, NaN);
// => 1 (successfully locates NaN)Both methods treat positive zero (+0) and negative zero
(-0) as equal:
_.indexOf([0], -0);
// => 0Internal Implementation in Lodash
Under the hood, Lodash implements this logic using helper functions to maximize performance:
- Fast Path (
strictIndexOf): When the target search value is notNaN(tested viavalue === value), Lodash uses a standard loop utilizing the strict equality operator (===). This allows standard primitive values and object references to be matched at maximum execution speed. - NaN Path (
baseFindIndex/isNaN): If the search value isNaN(tested viavalue !== value), Lodash switches to a loop that checks each element to see if it is alsoNaN.
By applying this internal branching, Lodash's _.indexOf
strictly conforms to the SameValueZero specification
without sacrificing the performance of standard equality checks for
non-NaN values.