deepmerge-plus
=============

> 深度合併兩個物件的可列舉屬性 / Merge the enumerable attributes of two objects deeply.

`pnpm add deepmerge-plus`

[***查看從版本 1.x 到 2.0.0 的變更 / Check out the changes from version 1.x to 2.0.0***](https://github.com/KyleAMathews/deepmerge/blob/master/changelog.md#200)

如需舊版（2.0.0 之前）的陣列元素合併演算法，請參閱下方的 [`arrayMerge` 選項](#arraymerge)。/ For the old array element-merging algorithm, see [the `arrayMerge` option below](#arraymerge).

example
=======

<!--js
var merge = require('./')
-->

```js
	var moment = require('moment')

	var monday = moment('2016-09-27T01:08:12.761Z')
	var tuesday = moment('2016-09-28T01:18:12.761Z')

	var target = {
		date: monday
	}
	var source = {
		date: tuesday
	}

	let options = {
		isMergeableObject(value, isMergeableObject) {
			let bool;

			if (bool = moment.isMoment(value)) {
				return false;
			}

			return isMergeableObject(value)
		}
	}

	var expected = {
		date: tuesday
	}
	var actual = merge(target, source, options) // => expected
```

```js
var x = {
	foo: { bar: 5 },
	array: [{
		does: 'work',
		too: [ 1, 2, 3 ]
	}]
}

var y = {
	foo: { baz: 4 },
	quux: 5,
	array: [{
		does: 'work',
		too: [ 4, 5, 6 ]
	}, {
		really: 'yes'
	}]
}

var expected = {
	foo: {
		bar: 5,
		baz: 4
	},
	array: [{
		does: 'work',
		too: [ 1, 2, 3 ]
	}, {
		does: 'work',
		too: [ 4, 5, 6 ]
	}, {
		really: 'yes'
	}],
	quux: 5
}

merge(x, y) // => expected
```

methods
=======

```
var merge = require('deepmerge')
```

merge(x, y, [options])
-----------

深度合併兩個物件 `x`和 `y`，返回一個包含兩者元素的新合併物件。/ Merge two objects `x` and `y` deeply, returning a new merged object with the elements from both `x` and `y`.

若 `x` 和 `y` 的同一個鍵都有元素存在，則結果中會顯示 `y` 的值。/ If an element at the same key is present for both `x` and `y`, the value from `y` will appear in the result.

合併會建立一個新物件，因此 `x` 和 `y` 都不會被修改。/ Merging creates a new object, so that neither `x` or `y` are be modified.

merge.all(arrayOfObjects, [options])
-----------

將任意數量的物件合併成單一結果物件。/ Merges any number of objects into a single result object.

```js
var x = { foo: { bar: 3 } }
var y = { foo: { baz: 4 } }
var z = { bar: 'yay!' }

var expected = { foo: { bar: 3, baz: 4 }, bar: 'yay!' }

merge.all([x, y, z]) // => expected
```

### options

#### arrayMerge

合併預設也會串聯陣列並合併陣列值。/ The merge will also concatenate arrays and merge array values by default.

然而，合併陣列有無限多種有效方式，您可以透過傳入 `arrayMerge` 函式來自訂合併行為。/ However, there are nigh-infinite valid ways to merge arrays, and you may want to supply your own.  You can do this by passing an `arrayMerge` function as an option.

```js
function overwriteMerge(destinationArray, sourceArray, options)
{
	return sourceArray
}

merge(
	[1, 2, 3],
	[3, 2, 1],
	{ arrayMerge: overwriteMerge }
) // => [3, 2, 1]
```

若要防止陣列被合併：/ To prevent arrays from being merged:

```js
const dontMerge = (destination, source) => source
const output = merge({ coolThing: [1,2,3] }, { coolThing: ['a', 'b', 'c'] }, { arrayMerge: dontMerge })
output // => { coolThing: ['a', 'b', 'c'] }
```

若要使用舊版（2.0.0 之前）的陣列合併演算法，請傳入此函式：/ To use the old (pre-version-2.0.0) array merging algorithm, pass in this function:

```js
const isMergeableObject = require('is-mergeable-object')
const emptyTarget = value => Array.isArray(value) ? [] : {}
const clone = (value, options) => merge(emptyTarget(value), value, options)

function oldArrayMerge(target, source, optionsArgument) {
	const destination = target.slice()

	source.forEach(function(e, i) {
		if (typeof destination[i] === 'undefined') {
			const cloneRequested = !optionsArgument || optionsArgument.clone !== false
			const shouldClone = cloneRequested && isMergeableObject(e)
			destination[i] = shouldClone ? clone(e, optionsArgument) : e
		} else if (isMergeableObject(e)) {
			destination[i] = merge(target[i], e, optionsArgument)
		} else if (target.indexOf(e) === -1) {
			destination.push(e)
		}
	})
	return destination
}

merge(
	[{ a: true }],
	[{ b: true }, 'ah yup'],
	{ arrayMerge: oldArrayMerge }
) // => [{ a: true, b: true }, 'ah yup']
```

#### clone

*已棄用 / *Deprecated.*

預設值為 `true`。/ Defaults to `true`.

若 `clone` 為 `false`，則子物件將直接複製而不會被複製。這是 2.x 版本之前的預設行為。/ If `clone` is `false` then child objects will be copied directly instead of being cloned.  This was the default behavior before version 2.x.

install
======

```bash
# 使用 npm / Using npm
pnpm add deepmerge-plus

# 使用 yarn / Using yarn
yarn add deepmerge-plus

# 使用 pnpm / Using pnpm
pnpm add deepmerge-plus
```

test
====

執行測試 / Run tests

```bash
pnpm test
```

license
======

MIT
