How Lodash Iteratee Converts Strings and Objects

In the Lodash JavaScript library, collection methods such as _.map, _.filter, and _.find do not require you to provide an explicit callback function. Instead, Lodash uses its internal adapter function, _.iteratee, to automatically transform strings, objects, and arrays into reusable callback functions. This article explains how _.iteratee detects different data types, the specific Lodash helpers it delegates to under the hood, and how these transformations streamline common data manipulation tasks.

The Role of _.iteratee

Whenever a Lodash method accepts a callback parameter (commonly documented as [iteratee=_.identity]), it wraps that argument with _.iteratee before processing the collection.

If the provided argument is already a function, _.iteratee simply returns it unchanged. However, if the argument is a string, an object, or an array, _.iteratee acts as a factory, matching the input type against specific internal constructors to generate a specialized predicate or accessor function.

Converting Strings: Property Shorthand

When passed a string (or a property path), _.iteratee delegates the transformation to _.property.

The generated function takes an object from the collection and returns the value at the specified key. It also supports deep dot-notation paths and array bracket notation.

// You write:
_.map(users, 'profile.name');

// _.iteratee transforms the string into:
_.map(users, _.property('profile.name'));

// Equivalent standard JavaScript:
users.map(user => user?.profile?.name);

Under the hood, _.property uses Lodash's path-retrieval logic (similar to _.get), ensuring that nested properties do not throw TypeError exceptions if intermediate properties are null or undefined.

Converting Objects: Matches Shorthand

When passed a plain JavaScript object, _.iteratee delegates to _.matches.

This generates a predicate function that performs a deep partial comparison against each item in the collection using _.isMatch. The generated function returns true only if the evaluated item contains identical keys and equivalent nested values to those defined in the target object.

// You write:
_.filter(users, { active: true, role: 'admin' });

// _.iteratee transforms the object into:
_.filter(users, _.matches({ active: true, role: 'admin' }));

// Equivalent standard JavaScript:
users.filter(user => user.active === true && user.role === 'admin');

This shorthand allows you to filter or find records based on deep object structures without manually chaining multiple equality checks.

Converting Two-Element Arrays: Property-Value Matching

When an array containing a key-value pair [key, value] is supplied, _.iteratee transforms it using _.matchesProperty.

This returns a predicate function that checks whether the property at the given key matches the specified value.

// You write:
_.find(users, ['status', 'pending']);

// _.iteratee transforms the array into:
_.find(users, _.matchesProperty('status', 'pending'));

// Equivalent standard JavaScript:
users.find(user => user.status === 'pending');

Like _.property, the key parameter in _.matchesProperty can be a nested path (e.g., ['account.status', 'pending']).

The Fallback: _.identity

If an iteratee argument is omitted, or if it is null or undefined, _.iteratee defaults to _.identity. The _.identity function simply returns the first argument provided to it (value => value). This is useful for flattening collections, filtering out falsy values via _.filter(array, Boolean) behavior, or extracting identical values.

Summary of the Transformation Pipeline

When any value enters _.iteratee, Lodash evaluates it in this order:

  1. Functions: Returned directly without modification.
  2. Plain Objects: Wrapped with _.matches(value) for deep partial equality.
  3. Arrays: Wrapped with _.matchesProperty(value[0], value[1]) for key-value checks.
  4. Strings / Numbers / Symbols: Wrapped with _.property(value) for property extraction.
  5. Null / Undefined / Other: Replaced with _.identity to return elements as-is.