Lodash _.parseInt vs Native parseInt in Mapping

JavaScript developers frequently encounter unexpected results when using native parseInt inside higher-order collection methods like Array.prototype.map, which often yields NaN due to unwanted argument passing. The Lodash library resolves this numeric mapping limitation with _.parseInt, which implements internal guards against iteratee arguments. This article explores the mechanical differences between the native engine implementation and Lodash's wrapper, demonstrating how argument consumption dictates parsing behavior during array operations.

The Native parseInt Mapping Pitfall

The native ECMAScript parseInt function accepts two parameters: string (the value to parse) and radix (an integer between 2 and 36 representing the numeral system base).

When applied directly as a callback to Array.prototype.map, a signature mismatch occurs. The map method provides three arguments to its callback on every iteration:

  1. currentValue
  2. index
  3. array

Because parseInt takes two arguments, it implicitly binds the array's index to the radix parameter:

['10', '10', '10', '10'].map(parseInt);
// Result: [10, NaN, 2, 3]

Under the hood, the native engine executes:

To avoid this limitation natively, developers must manually wrap the call in an arrow function: (val) => parseInt(val, 10).

How Lodash Overcomes the Mapping Limitation

Lodash’s _.parseInt explicitly prevents this radix contamination through an internal validation mechanism known as an iteratee guard (implemented via internal helpers like isIterateeCall).

When _.parseInt is invoked with three arguments—which is standard behavior for Lodash and native collection iteratees—it analyzes the second and third arguments. If the third argument is an object or array containing the first argument at the index specified by the second argument, Lodash recognizes that the function is being executed as an iteratee.

Upon detecting an iteratee call, _.parseInt ignores the second parameter (the index) rather than applying it as a radix. The radix then defaults to 10 (or automatically infers base 16 for strings prefixed with 0x or 0X):

import _ from 'lodash';

['10', '10', '10', '10'].map(_.parseInt);
// Result: [10, 10, 10, 10]

Key Differences Summary