You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					265 lines
				
				5.5 KiB
			
		
		
			
		
	
	
					265 lines
				
				5.5 KiB
			| 
											3 years ago
										 | # deepmerge
 | ||
|  | 
 | ||
|  | Merges the enumerable properties of two or more objects deeply. | ||
|  | 
 | ||
|  | > UMD bundle is 723B minified+gzipped
 | ||
|  | 
 | ||
|  | ## Getting Started
 | ||
|  | 
 | ||
|  | ### Example Usage
 | ||
|  | <!--js
 | ||
|  | const merge = require('./') | ||
|  | --> | ||
|  | 
 | ||
|  | ```js | ||
|  | 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](http://npmjs.org) do: | ||
|  | 
 | ||
|  | ```sh | ||
|  | 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](https://unpkg.com/deepmerge/dist/umd.js). | ||
|  | 
 | ||
|  | 
 | ||
|  | ### Include
 | ||
|  | 
 | ||
|  | deepmerge exposes a CommonJS entry point: | ||
|  | 
 | ||
|  | ``` | ||
|  | const merge = require('deepmerge') | ||
|  | ``` | ||
|  | 
 | ||
|  | The ESM entry point was dropped due to a [Webpack bug](https://github.com/webpack/webpack/issues/6584). | ||
|  | 
 | ||
|  | # 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. | ||
|  | 
 | ||
|  | ```js | ||
|  | 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: | ||
|  | 
 | ||
|  | ```js | ||
|  | 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. | ||
|  | 
 | ||
|  | ```js | ||
|  | 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`](https://github.com/jonschlinkert/is-plain-object). | ||
|  | 
 | ||
|  | ```js | ||
|  | 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. | ||
|  | 
 | ||
|  | ```js | ||
|  | 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](http://npmjs.org) do: | ||
|  | 
 | ||
|  | ```sh | ||
|  | npm test | ||
|  | ``` | ||
|  | 
 | ||
|  | 
 | ||
|  | # License
 | ||
|  | 
 | ||
|  | MIT |