Lodash's `merge()` Function

Apr 9, 2020

Given two objects destination and source, Lodash's merge() function copies the 2nd object's own properties and inherited properties into the first object.

const destination = { name: 'Will Riker', rank: 'Commander' };
const source = { ship: 'USS Enterprise' };

_.merge(destination, source);
destination.name; // 'Will Riker'
destination.rank; // 'Commander'
destination.ship; // 'USS Enterprise'

Sounds a lot like Object.assign(), right? While merge() is very similar to Object.assign() and _.assign(), there are a couple minor differences.

Differences Between merge() and assign()

The first detail is that merge() copies objects recursively, so _.merge() is a deep copy whereas _.assign() is a shallow copy.

const obj = {
  name: {
    first: 'Will',
    last: 'Riker'
  }
};

const deepClone = _.merge({}, obj);
deepClone.name === obj.name; // false

deepClone.name.first = 'Thomas';
obj.name.first; // 'Will'

const shallowClone = _.assign({}, obj);
shallowClone.name === obj.name; // true

shallowClone.name.first = 'Thomas';
obj.name.first; // 'Thomas'

The second detail is how merge() handles undefined. If the source has a key whose value is strictly equal to undefined, merge() will not overwrite that key in the destination.

let destination = {
  firstName: 'Will',
  lastName: 'Riker',
  rank: 'Commander'
};

// Since `source.rank` is undefined, `merge()` won't overwrite
// `destination.rank`.
_.merge(destination, { firstName: 'Thomas', rank: undefined });
destination.firstName; // 'Thomas'
destination.rank; // 'Commander'

destination = {
  firstName: 'Will',
  lastName: 'Riker',
  rank: 'Commander'
};
// But `_.assign()` and `Object.assign()` overwrite `destination.rank`.
_.assign(destination, { firstName: 'Thomas', rank: undefined });
destination.firstName; // 'Thomas'
destination.rank; // undefined

Another difference comes in when you consider how merge() handles classes.

class Ship {};
Ship.prototype.shipName = 'USS Enterprise';
const ship = new Ship();

// `merge()` copies inherited properties, so it will copy
// `shipName`
const merged = _.merge({ name: 'Will Riker', rank: 'Commander' }, ship);
merged.shipName; // 'USS Enterprise'

// `assign()` does **not** copy inherited properties.
const assigned = Object.assign({ name: 'Will Riker', rank: 'Commander' }, ship);
assigned.shipName; // undefined

Did you find this tutorial useful? Say thanks by starring our repo on GitHub!

More Lodash Tutorials