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

These libraries provide various functionalities for merging JavaScript objects. They allow developers to combine properties from multiple objects into a single object, handling nested structures and conflicts in different ways. Each library has its own approach to mutability, performance, and features, 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
deepmerge34,208,6582,75431.2 kB542 years agoMIT
lodash.merge32,604,19259,705-1085 years agoMIT
merge2,145,305177-114 years agoMIT
merge-options1,515,47169-14 years agoMIT
merge-deep1,056,607111-134 years agoMIT
object-assign-deep31,21370-97 years agoMIT
Feature Comparison: deepmerge vs lodash.merge vs merge vs merge-options vs merge-deep vs object-assign-deep

Merging Depth

  • deepmerge: deepmerge supports deep merging of nested objects and arrays, intelligently combining them while preserving their structure and handling conflicts gracefully.
  • lodash.merge: lodash.merge performs a shallow merge, which means it merges properties at the first level only, making it less suitable for deeply nested structures.
  • merge: merge provides deep merging capabilities, allowing for nested objects to be combined effectively, but may not handle arrays as intuitively as deepmerge.
  • merge-options: merge-options is designed for merging configuration objects, supporting deep merging while allowing default values to be set for missing properties.
  • merge-deep: merge-deep focuses on deep merging, ensuring that all levels of nested objects are combined correctly without losing data.
  • object-assign-deep: object-assign-deep extends the native Object.assign method to support deep merging, making it a simple and effective choice for projects needing deep object manipulation.

Mutability

  • deepmerge: deepmerge creates a new object for the merged result, ensuring immutability of the original objects, which is crucial for predictable state management.
  • lodash.merge: lodash.merge mutates the destination object, which may lead to unintended side effects if the original object is still in use elsewhere in the application.
  • merge: merge also mutates the destination object, making it important to be cautious about the original data being altered during the merge process.
  • merge-options: merge-options mutates the target object, which can be useful for managing configurations but requires careful handling to avoid unexpected changes.
  • merge-deep: merge-deep mutates the target object, so developers should be aware of the potential for side effects when using it in shared states.
  • object-assign-deep: object-assign-deep creates a new object for the merged result, maintaining immutability and preventing side effects on the original objects.

Performance

  • deepmerge: deepmerge is optimized for performance with complex structures, but may have overhead due to its deep merging capabilities, making it slower for very large objects.
  • lodash.merge: lodash.merge is generally fast for shallow merges but can slow down with deeply nested structures due to its mutative nature.
  • merge: merge is designed for efficiency in deep merging, balancing performance and functionality, making it suitable for most use cases without significant overhead.
  • merge-options: merge-options is efficient for merging configuration objects, ensuring fast performance while managing defaults and overrides effectively.
  • merge-deep: merge-deep is lightweight and focuses on performance, providing quick deep merges without unnecessary complexity.
  • object-assign-deep: object-assign-deep is performant for deep merges, leveraging the native Object.assign method for speed while maintaining functionality.

Use Cases

  • deepmerge: deepmerge is ideal for applications that require complex state management, such as Redux, where maintaining immutability is essential.
  • lodash.merge: lodash.merge is best suited for simple object merging tasks within projects already utilizing Lodash, providing a familiar API.
  • merge: merge is versatile and can be used in various scenarios where deep merging is necessary, such as combining user settings or configurations.
  • merge-options: merge-options is tailored for managing configuration objects, making it suitable for libraries or applications that need to handle default settings and user overrides.
  • merge-deep: merge-deep is perfect for straightforward merging tasks where deep merging is required without additional dependencies.
  • object-assign-deep: object-assign-deep is useful for projects that require deep merging while keeping the codebase simple and close to native JavaScript functionality.

Extensibility

  • deepmerge: deepmerge is extensible, allowing developers to customize the merging behavior by providing custom merge functions for specific types of data.
  • lodash.merge: lodash.merge is part of the Lodash ecosystem, making it easy to integrate with other Lodash utilities for enhanced functionality.
  • merge: merge is flexible and can be extended with custom merge strategies, allowing for tailored merging logic as needed.
  • merge-options: merge-options can be extended to handle specific merging scenarios, especially for configuration management, making it adaptable to different needs.
  • merge-deep: merge-deep is straightforward and does not offer extensive extensibility options, focusing instead on simplicity and ease of use.
  • object-assign-deep: object-assign-deep is simple and does not provide extensive extensibility, focusing on deep merging while keeping the API minimal.
How to Choose: deepmerge vs lodash.merge vs merge vs merge-options vs merge-deep vs object-assign-deep
  • deepmerge: Choose deepmerge when you need a robust solution for deeply nested object merging, as it intelligently merges arrays and objects while preserving the original structure.
  • lodash.merge: Select lodash.merge if you are already using Lodash in your project and require a simple, straightforward merge function that handles shallow merging of objects.
  • merge: Opt for merge if you want a lightweight and flexible library that supports deep merging with a focus on simplicity and ease of use.
  • merge-options: Choose merge-options when you need to merge configuration objects with support for default values, allowing you to easily manage options in your applications.
  • merge-deep: Use merge-deep for a straightforward deep merge solution without additional dependencies, especially if you want a minimalistic approach to merging objects.
  • object-assign-deep: Select object-assign-deep if you prefer a simple, deep merge solution that extends the native Object.assign method, especially for projects that require deep merging without additional overhead.
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