| # 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 |