How Lodash mapValues Transforms Object Values

This article explores how the _.mapValues function in the Lodash JavaScript library transforms object values. It details the role of the iteratee function, the arguments passed to it during iteration, the default behavior when no iteratee is provided, and the various iteratee shorthand notations supported by Lodash.

The Role of the Iteratee in _.mapValues

In Lodash, _.mapValues(object, [iteratee=_.identity]) creates an object with the same keys as the source object, while generating new values by running each own enumerable string-keyed property through a transformation function known as the iteratee.

By default, if no iteratee is provided, Lodash uses _.identity, which simply returns the original value unchanged.

Arguments Passed to the Iteratee

When a custom iteratee function is passed to _.mapValues, it is invoked once for each property in the object with three specific arguments:

  1. value: The value of the current property being processed.
  2. key: The key of the current property being processed.
  3. object: The source object being iterated over.

Example Using a Function Iteratee

const _ = require('lodash');

const users = {
  fred: { user: 'fred', age: 40 },
  pebbles: { user: 'pebbles', age: 1 }
};

// Custom iteratee using only the value argument
const ages = _.mapValues(users, (value) => value.age);
// Output: { fred: 40, pebbles: 1 }

// Custom iteratee using both value and key arguments
const greetings = _.mapValues(users, (value, key) => `${key} is ${value.age} years old`);
// Output: { fred: 'fred is 40 years old', pebbles: 'pebbles is 1 years old' }

Supported Iteratee Shorthands

Lodash provides shorthand notations that can be passed in place of a standard callback function. _.mapValues automatically adapts these shorthands using internal iteratee helpers:

1. Property Name Shorthand (_.property)

Passing a string or property path transforms each value by retrieving the specified nested property.

const users = {
  fred: { user: 'fred', age: 40 },
  pebbles: { user: 'pebbles', age: 1 }
};

// Uses the string 'age' as a shorthand for (o) => o.age
const result = _.mapValues(users, 'age');
// Output: { fred: 40, pebbles: 1 }

2. Matches Property Shorthand (_.matchesProperty)

Passing a key-value array creates an iteratee that checks if a nested property equals the given value, returning a boolean.

const users = {
  fred: { role: 'admin', active: true },
  barney: { role: 'user', active: false }
};

const isAdmin = _.mapValues(users, ['role', 'admin']);
// Output: { fred: true, barney: false }

3. Matches Object Shorthand (_.matches)

Passing an object creates an iteratee that performs a deep comparison between the source object's values and the given object, returning a boolean.

const users = {
  fred: { role: 'admin', active: true },
  barney: { role: 'user', active: false }
};

const isExactAdmin = _.mapValues(users, { role: 'admin', active: true });
// Output: { fred: true, barney: false }

Through functions or shorthand expressions, the iteratee in _.mapValues specifically targets and recalculates the values of an object while keeping the structural keys intact.