How Lodash _.max Bypasses Array Prototype Properties

Lodash's _.max bypasses prototype properties when processing large numeric arrays by utilizing index-based iteration constrained by the array's length property rather than object key enumeration. Instead of traversing object keys using mechanisms that climb the prototype chain, Lodash delegates the operation to internal base methods that access elements via sequential integer indexes. This approach ensures maximum execution speed on massive datasets, prevents inherited properties from polluting calculations, and enables JavaScript engines to optimize memory access patterns.

Index-Based Traversal via baseExtremum

Under the hood, _.max delegates evaluation to an internal function named baseExtremum. Rather than using a for...in loop—which enumerates all enumerable properties across the entire prototype chain—baseExtremum uses an optimized while loop:

function baseExtremum(array, iteratee, comparator) {
  let index = -1;
  const length = array.length;
  let result;
  let computed;

  while (++index < length) {
    const value = array[index];
    const current = iteratee(value);

    if (current != null && (computed === undefined
          ? (current === current && !isSymbol(current))
          : comparator(current, computed)
        )) {
      computed = current;
      result = value;
    }
  }
  return result;
}

Because the loop counter increments from 0 up to length - 1, Lodash only requests numeric properties bounded by the current length of the array. Named properties, extensions, or custom helper functions appended to Array.prototype or Object.prototype (such as Array.prototype.customValue = 999999) are never targeted.

Avoiding Property Enumeration

Standard property enumeration via for...in visits every enumerable property on the object and its prototype chain, requiring explicit guards like Object.prototype.hasOwnProperty.call(array, key) to filter out prototype extensions. Executing hasOwnProperty across an array containing millions of elements adds severe overhead.

By utilizing indexed element retrieval (array[index]), Lodash avoids property enumeration entirely:

Engine-Level Optimizations (V8 Fast Elements)

Directly accessing elements through sequential integer indices allows JavaScript engines like V8 to keep the array in a "fast elements" state (such as PACKED_SMI_ELEMENTS or PACKED_DOUBLE_ELEMENTS).

When code uses property-enumeration loops or accesses arbitrary prototype properties, engines may fall back to "dictionary mode" (slow properties), which stores elements as a hash table. By sticking to dense numeric loops, _.max enables the engine to predict memory offsets linearly, load data into CPU caches efficiently, and inline the comparison operations without triggering deoptimizations.

Handling of Sparse Arrays and Non-Values

In extreme edge cases involving sparse arrays (e.g., new Array(1000000)), accessing an unassigned index via array[index] evaluates to undefined unless a matching numeric index explicitly exists on Array.prototype.

Lodash protects the calculation against these cases through its comparison checks:

  1. It validates that values are non-null and not undefined.
  2. It handles NaN values via self-equality checks (current === current).
  3. If an index does not contain a valid primitive number, the comparator ignores it, preventing faulty comparisons from setting an invalid maximum.