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; // true

Because 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:

  1. If either operand is NaN, the result is false.
  2. If the values are identical numbers, the result is true.
  3. If one value is +0 and the other is -0, the result is true.

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:

  1. baseIndexOf: Determines whether the search target requires special handling (such as NaN, which cannot match itself using strict equality).
  2. 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 1

Distinguishing 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.