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.
264 lines
5.5 KiB
264 lines
5.5 KiB
# 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
|
|
|