How Lodash _.includes Checks for NaN

In JavaScript, standard strict equality checks fail when identifying NaN because NaN === NaN evaluates to false. This article explores how Lodash’s _.includes method overcomes this native limitation by utilizing the SameValueZero equality algorithm alongside an internal self-inequality check, ensuring that NaN values within arrays and collections are reliably and securely detected.

The NaN Comparison Problem in JavaScript

Under the ECMAScript specification, NaN (Not-a-Number) is unique because it is the only value in JavaScript that is not equal to itself:

console.log(NaN === NaN); // false
console.log([NaN].indexOf(NaN)); // -1

Because native methods historically relied on the Strict Equality Comparison algorithm (===), methods like Array.prototype.indexOf could not locate NaN.

The SameValueZero Algorithm

Lodash avoids this failure by standardizing its collection and comparison utilities around the SameValueZero comparison algorithm.

SameValueZero behaves almost identically to strict equality (===), with two major exceptions:

  1. +0 and -0 are considered equal.
  2. NaN and NaN are considered equal.

By following this specification, _.includes ensures mathematical consistency across search operations.

How Lodash Implements NaN Detection

To execute SameValueZero efficiently without performance overhead, Lodash employs a conditional branch inside its internal indexing pipeline (primarily within baseIndexOf and associated helper utilities).

1. The Self-Inequality Test

Lodash first determines whether the target value is NaN by exploiting JavaScript's self-inequality property:

function isNaNValue(value) {
  return value !== value;
}

If target !== target evaluates to true, the search value is guaranteed to be NaN.

2. Branching to nanIndexOf

Once the target value is identified as NaN, Lodash bypasses standard strict-equality loops and directs the search to a specialized scanning routine, historically implemented as nanIndexOf or an equivalent custom loop using baseFindIndex:

function nanIndexOf(array, fromIndex) {
  let index = fromIndex - 1;
  const { length } = array;

  while (++index < length) {
    const value = array[index];
    if (value !== value) {
      return index;
    }
  }
  return -1;
}

This loop inspects each element in the collection and checks if the element is not equal to itself (value !== value). When an element satisfies this condition, it confirms the presence of NaN at that index.

3. Returning the Result

If nanIndexOf finds a valid match (returning an index of 0 or greater), _.includes evaluates the result to true. If the loop terminates without finding an element that satisfies value !== value, it returns -1, resolving _.includes to false.

Through this mechanism, Lodash securely verifies the presence of NaN while avoiding false negatives and preserving high-performance execution for all standard data types.