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:

  1. If Type(x) is different from Type(y), return false.
  2. If x is NaN and y is NaN, return true.
  3. If x is +0 and y is -0 (or vice versa), return true.
  4. 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); 
// => 0

Internal Implementation in Lodash

Under the hood, Lodash implements this logic using helper functions to maximize performance:

  1. Fast Path (strictIndexOf): When the target search value is not NaN (tested via value === 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.
  2. NaN Path (baseFindIndex / isNaN): If the search value is NaN (tested via value !== value), Lodash switches to a loop that checks each element to see if it is also NaN.

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.