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

These libraries provide various methods for merging objects in JavaScript, allowing developers to combine properties from multiple sources into a single object. They differ in their handling of nested objects, mutability, and performance, making them suitable for different use cases in web development. Understanding the nuances of each library can help developers choose the right tool for their specific merging needs.

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
merge-options1,513,09669-14 years agoMIT
merge-deep1,036,948111-134 years agoMIT
deep-assign196,999247-06 years agoMIT
object-assign-deep29,42870-97 years agoMIT
Feature Comparison: deepmerge vs lodash.merge vs merge-options vs merge-deep vs deep-assign vs object-assign-deep

Deep Merging

  • deepmerge: deepmerge excels in deep merging, allowing for complex structures, including arrays and nested objects. It supports custom merging strategies, giving developers control over how properties are combined.
  • lodash.merge: lodash.merge performs deep merging by recursively merging properties of source objects into the destination object. It handles arrays by concatenating them, which may not always be the desired behavior.
  • merge-options: merge-options is specifically designed for merging configuration objects, handling nested properties while ensuring immutability. It is ideal for managing options in a clean and efficient manner.
  • merge-deep: merge-deep offers a simple API for deep merging, focusing on merging properties without additional features. It is lightweight and easy to use for basic merging needs.
  • deep-assign: deep-assign provides a straightforward approach to deeply merge objects, copying properties from source objects to the target object recursively. It does not mutate the original objects, ensuring data integrity.
  • object-assign-deep: object-assign-deep extends the functionality of Object.assign to support deep merging, allowing developers to use a familiar API while benefiting from deep merging capabilities.

Mutability

  • deepmerge: deepmerge allows for mutable and immutable merging strategies, giving developers the option to choose whether to modify the original objects or create new ones.
  • lodash.merge: lodash.merge mutates the destination object, which can lead to unintended side effects if not handled carefully. It is important to ensure that the destination object is a fresh instance if immutability is desired.
  • merge-options: merge-options maintains immutability by returning a new object that combines the properties of the input options, making it suitable for functional programming styles.
  • merge-deep: merge-deep does not mutate the original objects, ensuring that the source and target remain unchanged after the merge operation.
  • deep-assign: deep-assign does not mutate the source or target objects, making it safe to use in scenarios where data integrity is crucial.
  • object-assign-deep: object-assign-deep does not mutate the original objects, providing a safe way to perform deep merges while keeping the source data intact.

Performance

  • deepmerge: deepmerge may incur performance costs for very large or deeply nested objects due to its comprehensive merging strategies, but it is optimized for complex scenarios.
  • lodash.merge: lodash.merge is highly optimized for performance and can handle large datasets efficiently, but its mutability can lead to performance issues if not managed properly.
  • merge-options: merge-options is efficient for merging configuration objects and is optimized for handling nested properties without significant performance overhead.
  • merge-deep: merge-deep is designed for simplicity and speed, making it a good choice for projects that require quick and efficient deep merging without additional complexity.
  • deep-assign: deep-assign is lightweight and performs well for basic deep merging tasks, making it suitable for applications with minimal performance overhead.
  • object-assign-deep: object-assign-deep performs well for deep merging while maintaining a familiar API, making it a good choice for projects that prioritize performance and ease of use.

Use Cases

  • deepmerge: deepmerge is best suited for complex applications that require advanced merging capabilities, such as state management in frameworks like Redux or Vuex.
  • lodash.merge: lodash.merge is perfect for projects already utilizing Lodash, where deep merging is needed alongside other Lodash utilities, such as data manipulation and transformation.
  • merge-options: merge-options is specifically designed for scenarios where merging configuration options is necessary, such as in plugin systems or API clients.
  • merge-deep: merge-deep is a great choice for lightweight applications that need basic deep merging functionality without the overhead of a larger library.
  • deep-assign: deep-assign is ideal for simple applications where deep merging is required without additional complexity, such as merging user settings or configuration objects.
  • object-assign-deep: object-assign-deep is useful in projects that prefer a native JavaScript style for merging objects while requiring deep merging capabilities.

Documentation and Community

  • deepmerge: deepmerge is well-documented with examples and use cases, making it easy for developers to understand its capabilities and integrate it into their projects.
  • lodash.merge: lodash.merge benefits from extensive documentation and a large community, providing ample resources for troubleshooting and best practices.
  • merge-options: merge-options is documented clearly with a focus on its intended use case for merging options, making it easy to understand for new users.
  • merge-deep: merge-deep has concise documentation that covers its core functionality, making it easy to get started without overwhelming details.
  • deep-assign: deep-assign has straightforward documentation that is easy to follow, making it accessible for beginners and quick to implement in projects.
  • object-assign-deep: object-assign-deep has adequate documentation that aligns with its familiar API, helping developers transition smoothly from native methods.
How to Choose: deepmerge vs lodash.merge vs merge-options vs merge-deep vs deep-assign vs object-assign-deep
  • deepmerge: Opt for deepmerge if you require a robust solution that can handle complex merging scenarios, including arrays and nested objects. It offers customizable merging strategies, making it suitable for more advanced use cases.
  • lodash.merge: Select lodash.merge if you are already using Lodash in your project and want a reliable merging function that integrates seamlessly with other Lodash utilities. It provides a solid performance and is well-documented.
  • merge-options: Choose merge-options if you need to merge options objects, particularly for configuration settings. It is designed to handle merging of options with a focus on immutability and simplicity.
  • merge-deep: Use merge-deep for a lightweight solution that focuses on deep merging with a simple API. It is ideal for projects that need basic deep merging without the overhead of additional features.
  • deep-assign: Choose deep-assign if you need a simple and straightforward way to merge objects deeply without worrying about mutability. It is lightweight and focuses solely on deep merging without additional features.
  • object-assign-deep: Select object-assign-deep if you prefer a familiar API similar to Object.assign but require deep merging capabilities. It is useful for projects that need to maintain a consistent style with native JavaScript methods.
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