Deep Mapping Restrictions in Lodash mapValues

The Lodash utility _.mapValues creates an object with the same keys as the source object, applying an iteratee to generate each mapped value. This article examines the explicit conditions, structural constraints, and architectural boundaries within the Lodash library that prevent _.mapValues from deeply, recursively, and completely evaluating nested data structures out of the box.

Inherent Shallow Iteration

The primary restriction preventing _.mapValues from deeply evaluating nested properties is that it is strictly shallow by design. The function iterates exclusively across the immediate, top-level keys of the supplied object. When an object contains nested objects or arrays, _.mapValues passes the child container into the iteratee as an opaque reference rather than descending into its children. Without explicit manual recursion defined inside the callback, nested variables remain untouched.

Enumerable and Own-Property Boundaries

Lodash restricts property traversal according to standard JavaScript object descriptor rules:

Symbol-Key Exclusion

Standard _.mapValues execution is strictly restricted to string-keyed properties. Symbols introduced in ECMAScript 2015 (Symbol()) used as property identifiers are not retrieved during iteration. Lodash does not invoke Object.getOwnPropertySymbols inside the standard _.mapValues pipeline, completely omitting symbol-mapped values from the transformation process.

Array and Data Structure Coercion

When supplied with an array or array-like structure rather than a plain object, _.mapValues still executes its object-mapping strategy:

This structural coercion prevents direct, homogenous deep mapping when mixed hierarchies of objects and arrays are involved.

Lack of Native Short-Circuiting or Lazy Context

_.mapValues does not operate lazily unless integrated with explicit Lodash wrapper chains (_(obj)), and even within lazy sequences, it processes properties eagerly upon unwrapping (.value()). It lacks built-in conditional mechanisms to deeply pause, abort, or conditionally branch into branch nodes versus leaf nodes.

Implementing Complete Deep Evaluation

Because _.mapValues strictly restricts its scope to the first level of own-enumerable string properties, developers requiring deep evaluation must use alternative patterns: