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

These libraries provide various methods for merging JavaScript objects, each with its own approach to handling properties, mutability, and deep merging. They are essential tools for developers who need to combine object properties efficiently and effectively, especially in scenarios involving complex data structures or configurations. Understanding the differences between these libraries can help developers choose the right tool for their specific use cases, whether they require simple property assignment or complex deep merging capabilities.

NPM Package Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
deepmerge34,226,6792,75531.2 kB542 years agoMIT
lodash.merge32,627,90159,696-1085 years agoMIT
lodash.assign1,938,16359,696-1088 years agoMIT
merge-options1,513,09669-14 years agoMIT
merge-deep1,036,948111-134 years agoMIT
object-assign-deep29,42870-97 years agoMIT
Feature Comparison: deepmerge vs lodash.merge vs lodash.assign vs merge-options vs merge-deep vs object-assign-deep

Deep Merging

  • deepmerge: Deepmerge provides a powerful deep merging function that intelligently combines nested objects and arrays, allowing you to specify custom merging strategies for specific types, ensuring that complex structures are merged correctly without losing data.
  • lodash.merge: Lodash.merge offers deep merging capabilities, combining properties from source objects into a target object recursively. It handles nested objects and arrays, making it a versatile choice for complex data structures.
  • lodash.assign: Lodash.assign performs a shallow merge, meaning it only copies properties from source objects to the target object at the first level. It does not merge nested objects, making it unsuitable for deep merging scenarios.
  • merge-options: Merge-options allows for merging of configuration objects, providing flexibility in how properties are combined, especially useful for managing default settings and overrides in applications.
  • merge-deep: Merge-deep focuses on deep merging without additional features, providing a simple and effective way to combine nested objects. It is lightweight and easy to use for straightforward merging tasks.
  • object-assign-deep: Object-assign-deep combines properties from source objects into a target object recursively, maintaining immutability. It is designed for functional programming paradigms, ensuring that original objects remain unchanged.

Mutability

  • deepmerge: Deepmerge is immutable by default, meaning it does not alter the original objects during the merging process. This is crucial for maintaining state integrity in applications where data immutability is important.
  • lodash.merge: Lodash.merge also mutates the target object, which is important to consider when managing state in applications. It can lead to side effects if the original object is referenced after the merge.
  • lodash.assign: Lodash.assign mutates the target object directly, which can lead to unintended side effects if the original object is still in use elsewhere in the application. Use with caution in mutable contexts.
  • merge-options: Merge-options can mutate the target object, depending on how it is used. Be mindful of its behavior when merging configuration objects to avoid side effects.
  • merge-deep: Merge-deep is designed to be non-mutating, ensuring that the original objects remain unchanged after the merge operation, making it safe to use in functional programming contexts.
  • object-assign-deep: Object-assign-deep is immutable, creating a new object for the merged result while leaving the original objects intact, which is beneficial for functional programming and state management.

Performance

  • deepmerge: Deepmerge is optimized for performance in deep merging scenarios, but it may be slower than shallow merging methods due to the complexity of handling nested structures. It is best used when deep merging is necessary.
  • lodash.merge: Lodash.merge is performant for deep merging but can become slower with deeply nested structures due to the recursive nature of the operation. It is suitable for moderate complexity merging tasks.
  • lodash.assign: Lodash.assign is highly performant for shallow merges, making it ideal for scenarios where only top-level properties need to be combined, minimizing overhead.
  • merge-options: Merge-options is efficient for merging configuration objects, but performance may vary based on the complexity of the objects being merged. It is designed for flexibility rather than raw speed.
  • merge-deep: Merge-deep is lightweight and efficient for deep merging, making it a good choice for smaller projects or when simplicity is preferred over extensive features.
  • object-assign-deep: Object-assign-deep is designed for performance in deep merging while maintaining immutability, making it a solid choice for functional programming without sacrificing speed.

Ease of Use

  • deepmerge: Deepmerge has a straightforward API that is easy to understand, making it accessible for developers who need to perform complex merges without a steep learning curve.
  • lodash.merge: Lodash.merge is also user-friendly, providing a familiar lodash syntax for those already accustomed to the library, making it easy to integrate into existing projects.
  • lodash.assign: Lodash.assign is very easy to use, with a simple syntax that allows developers to quickly merge properties without needing to understand complex merging logic.
  • merge-options: Merge-options has a clear API that is easy to grasp, especially for developers familiar with configuration management, making it user-friendly for merging options.
  • merge-deep: Merge-deep offers a simple and intuitive API, making it easy to implement in projects without requiring extensive documentation or learning.
  • object-assign-deep: Object-assign-deep provides a simple interface for deep merging, making it easy to use in functional programming contexts without additional complexity.

Community and Support

  • deepmerge: Deepmerge has a growing community and is well-documented, providing sufficient resources for developers to troubleshoot and implement the library effectively.
  • lodash.merge: Lodash.merge benefits from the extensive lodash ecosystem, with strong community support and comprehensive documentation to assist developers.
  • lodash.assign: Lodash is widely used and has a large community, ensuring ample support, documentation, and resources available for developers.
  • merge-options: Merge-options has a smaller community but is straightforward enough for developers to find help in general JavaScript forums and documentation.
  • merge-deep: Merge-deep is less popular than lodash but has a dedicated user base and sufficient documentation for basic usage, though it may lack extensive community resources.
  • object-assign-deep: Object-assign-deep has a modest community presence, but its simplicity makes it easy to use without needing extensive support.
How to Choose: deepmerge vs lodash.merge vs lodash.assign vs merge-options vs merge-deep vs object-assign-deep
  • deepmerge: Choose deepmerge if you need a robust solution for deep merging objects that can handle arrays and nested structures intelligently, preserving the original objects without mutation.
  • lodash.merge: Select lodash.merge when you require deep merging capabilities with the ability to handle nested objects and arrays, while also benefiting from lodash's extensive utility functions for other operations.
  • lodash.assign: Use lodash.assign for simple, shallow property assignments where performance is critical and deep merging is not required. It is ideal for merging properties from one or more source objects into a target object without affecting nested properties.
  • merge-options: Use merge-options when you need to merge configuration objects where you want to control the merging behavior, especially in scenarios involving default options and overrides.
  • merge-deep: Opt for merge-deep if you want a straightforward approach to deep merging objects without additional dependencies, focusing on simplicity and ease of use in smaller projects.
  • object-assign-deep: Choose object-assign-deep if you prefer a simple API for deep merging while maintaining immutability, making it suitable for functional programming styles.
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