Which is Better JavaScript Object Merging Libraries?
deepmerge vs lodash.merge vs merge-options vs merge-deep
1 Year
deepmergelodash.mergemerge-optionsmerge-deepSimilar Packages:
What's JavaScript Object Merging Libraries?

These libraries provide utilities for merging JavaScript objects, allowing developers to combine properties from multiple sources into a single target object. They are essential for managing state in applications, especially when dealing with configuration objects, state management, or any scenario where object composition is required. Each library has its own approach to handling deep merges, mutability, and performance considerations, making them suitable for different use cases in web development.

NPM Package Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
deepmerge36,580,7382,75831.2 kB542 years agoMIT
lodash.merge34,876,19359,769-1155 years agoMIT
merge-options1,631,38769-14 years agoMIT
merge-deep1,082,511111-144 years agoMIT
Feature Comparison: deepmerge vs lodash.merge vs merge-options vs merge-deep

Merging Depth

  • deepmerge: deepmerge supports deep merging of objects, including nested structures and arrays. It intelligently combines properties, ensuring that all levels of the object hierarchy are considered during the merge process, making it ideal for complex data structures.
  • lodash.merge: lodash.merge performs a shallow merge of properties, meaning it only merges properties at the first level. For nested objects, it will overwrite the entire property rather than merging it, which can lead to data loss if not handled carefully.
  • merge-options: merge-options allows for customizable merging strategies, including deep merging. You can specify how to handle conflicts and define custom merge functions for specific properties, offering flexibility in how options are combined.
  • merge-deep: merge-deep provides deep merging capabilities similar to deepmerge but is designed to be lightweight. It merges properties recursively, allowing for the combination of deeply nested objects without losing data.

Mutability

  • deepmerge: deepmerge creates a new object for each merge operation, ensuring immutability. This is beneficial in functional programming paradigms where maintaining the original object state is crucial, especially in state management scenarios.
  • lodash.merge: lodash.merge modifies the target object in place, which can lead to unintended side effects if the original object is used elsewhere. This mutability can be a drawback in applications that rely on immutability for state management.
  • merge-options: merge-options can be configured for either mutable or immutable merging, depending on how you set it up. This flexibility allows you to choose the approach that best fits your application's architecture.
  • merge-deep: merge-deep also maintains immutability by returning a new object for each merge operation. This makes it suitable for functional programming practices and helps prevent side effects in your application.

Performance

  • deepmerge: deepmerge is optimized for performance with complex nested structures, but it may be slower than simpler libraries for shallow merges due to its recursive nature. It is best used when deep merging is necessary for the application's functionality.
  • lodash.merge: lodash.merge is highly optimized for performance and is generally faster for shallow merges. However, its performance may degrade with deeply nested objects due to the way it handles merging, which can lead to inefficiencies in larger datasets.
  • merge-options: merge-options is also performance-oriented, particularly when dealing with option merging. It allows for quick merges with customizable strategies, ensuring that performance remains optimal even in complex scenarios.
  • merge-deep: merge-deep is designed to be lightweight and efficient, making it a good choice for performance-sensitive applications that require deep merging without the overhead of larger libraries.

Ease of Use

  • deepmerge: deepmerge has a straightforward API that is easy to use for developers familiar with JavaScript object manipulation. Its clear documentation helps users quickly understand how to implement deep merging in their projects.
  • lodash.merge: lodash.merge benefits from the extensive Lodash documentation and community support, making it easy to integrate into existing projects. Developers familiar with Lodash will find it intuitive to use.
  • merge-options: merge-options provides a flexible API that may require a bit more understanding to fully utilize its capabilities. However, its customization options can be very powerful once mastered, making it a great choice for advanced use cases.
  • merge-deep: merge-deep offers a simple API that is easy to understand and implement. Its lightweight nature makes it a quick solution for developers looking for a no-frills merging utility.

Community and Support

  • deepmerge: deepmerge has a smaller community compared to Lodash, but it is well-maintained and has a clear focus on deep merging. Support is available through GitHub issues and documentation.
  • lodash.merge: lodash.merge is part of the larger Lodash library, which has a vast community and extensive support. It is widely used in the JavaScript ecosystem, ensuring plenty of resources and examples are available.
  • merge-options: merge-options is less commonly used but offers good documentation and support through its GitHub repository. It may not have as large a community as Lodash, but it is still a reliable choice for option merging.
  • merge-deep: merge-deep has a smaller user base, but it is actively maintained. Documentation is clear, and community support can be found through GitHub and other developer forums.
How to Choose: deepmerge vs lodash.merge vs merge-options vs merge-deep
  • deepmerge: Choose deepmerge if you need a robust solution for deep merging objects that can handle nested structures and arrays effectively. It is particularly useful when you want to merge complex configurations or state objects without losing any data.
  • lodash.merge: Select lodash.merge if you are already using Lodash in your project and prefer a familiar API. It provides a straightforward way to merge objects, but it does not handle arrays as deeply as some other options, making it less suitable for complex nested structures.
  • merge-options: Use merge-options when you want a flexible and customizable merging strategy, especially for handling options in libraries or APIs. It allows you to define how merging should occur, making it suitable for scenarios where you need fine-grained control over the merge process.
  • merge-deep: Opt for merge-deep if you need a lightweight solution focused on deep merging without additional dependencies. It is ideal for projects that require a simple and efficient way to merge objects while maintaining immutability.
README for deepmerge

deepmerge

Merges the enumerable properties of two or more objects deeply.

UMD bundle is 723B minified+gzipped

Getting Started

Example Usage

const x = {
	foo: { bar: 3 },
	array: [{
		does: 'work',
		too: [ 1, 2, 3 ]
	}]
}

const y = {
	foo: { baz: 4 },
	quux: 5,
	array: [{
		does: 'work',
		too: [ 4, 5, 6 ]
	}, {
		really: 'yes'
	}]
}

const output = {
	foo: {
		bar: 3,
		baz: 4
	},
	array: [{
		does: 'work',
		too: [ 1, 2, 3 ]
	}, {
		does: 'work',
		too: [ 4, 5, 6 ]
	}, {
		really: 'yes'
	}],
	quux: 5
}

merge(x, y) // => output

Installation

With npm do:

npm install deepmerge

deepmerge can be used directly in the browser without the use of package managers/bundlers as well: UMD version from unpkg.com.

Include

deepmerge exposes a CommonJS entry point:

const merge = require('deepmerge')

The ESM entry point was dropped due to a Webpack bug.

API

merge(x, y, [options])

Merge two objects x and y deeply, returning a new merged object with the elements from both x and y.

If an element at the same key is present for both x and y, the value from y will appear in the result.

Merging creates a new object, so that neither x or y is modified.

Note: By default, arrays are merged by concatenating them.

merge.all(arrayOfObjects, [options])

Merges any number of objects into a single result object.

const foobar = { foo: { bar: 3 } }
const foobaz = { foo: { baz: 4 } }
const bar = { bar: 'yay!' }

merge.all([ foobar, foobaz, bar ]) // => { foo: { bar: 3, baz: 4 }, bar: 'yay!' }

Options

arrayMerge

There are multiple ways to merge two arrays, below are a few examples but you can also create your own custom function.

Your arrayMerge function will be called with three arguments: a target array, the source array, and an options object with these properties:

  • isMergeableObject(value)
  • cloneUnlessOtherwiseSpecified(value, options)

arrayMerge example: overwrite target array

Overwrites the existing array values completely rather than concatenating them:

const overwriteMerge = (destinationArray, sourceArray, options) => sourceArray

merge(
	[1, 2, 3],
	[3, 2, 1],
	{ arrayMerge: overwriteMerge }
) // => [3, 2, 1]

arrayMerge example: combine arrays

Combines objects at the same index in the two arrays.

This was the default array merging algorithm pre-version-2.0.0.

const combineMerge = (target, source, options) => {
	const destination = target.slice()

	source.forEach((item, index) => {
		if (typeof destination[index] === 'undefined') {
			destination[index] = options.cloneUnlessOtherwiseSpecified(item, options)
		} else if (options.isMergeableObject(item)) {
			destination[index] = merge(target[index], item, options)
		} else if (target.indexOf(item) === -1) {
			destination.push(item)
		}
	})
	return destination
}

merge(
	[{ a: true }],
	[{ b: true }, 'ah yup'],
	{ arrayMerge: combineMerge }
) // => [{ a: true, b: true }, 'ah yup']

isMergeableObject

By default, deepmerge clones every property from almost every kind of object.

You may not want this, if your objects are of special types, and you want to copy the whole object instead of just copying its properties.

You can accomplish this by passing in a function for the isMergeableObject option.

If you only want to clone properties of plain objects, and ignore all "special" kinds of instantiated objects, you probably want to drop in is-plain-object.

const { isPlainObject } = require('is-plain-object')

function SuperSpecial() {
	this.special = 'oh yeah man totally'
}

const instantiatedSpecialObject = new SuperSpecial()

const target = {
	someProperty: {
		cool: 'oh for sure'
	}
}

const source = {
	someProperty: instantiatedSpecialObject
}

const defaultOutput = merge(target, source)

defaultOutput.someProperty.cool // => 'oh for sure'
defaultOutput.someProperty.special // => 'oh yeah man totally'
defaultOutput.someProperty instanceof SuperSpecial // => false

const customMergeOutput = merge(target, source, {
	isMergeableObject: isPlainObject
})

customMergeOutput.someProperty.cool // => undefined
customMergeOutput.someProperty.special // => 'oh yeah man totally'
customMergeOutput.someProperty instanceof SuperSpecial // => true

customMerge

Specifies a function which can be used to override the default merge behavior for a property, based on the property name.

The customMerge function will be passed the key for each property, and should return the function which should be used to merge the values for that property.

It may also return undefined, in which case the default merge behaviour will be used.

const alex = {
	name: {
		first: 'Alex',
		last: 'Alexson'
	},
	pets: ['Cat', 'Parrot']
}

const tony = {
	name: {
		first: 'Tony',
		last: 'Tonison'
	},
	pets: ['Dog']
}

const mergeNames = (nameA, nameB) => `${nameA.first} and ${nameB.first}`

const options = {
	customMerge: (key) => {
		if (key === 'name') {
			return mergeNames
		}
	}
}

const result = merge(alex, tony, options)

result.name // => 'Alex and Tony'
result.pets // => ['Cat', 'Parrot', 'Dog']

clone

Deprecated.

Defaults to true.

If clone is false then child objects will be copied directly instead of being cloned. This was the default behavior before version 2.x.

Testing

With npm do:

npm test

License

MIT