-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
134 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
function getType(o) { | ||
return Object.prototype.toString.call(o); | ||
} | ||
|
||
function deepClone(obj, weakMap = new WeakMap()) { | ||
const type = Object.prototype.toString.call(obj); | ||
if (!(type === '[object Object]' || type === '[object Array]')) return obj; | ||
const o = type === '[object Object]' ? {} : []; | ||
if (weakMap.get(obj)) return o; | ||
weakMap.set(obj, true); | ||
for (const key in obj) { | ||
if (obj.hasOwnProperty(key)) { | ||
o[key] = deepClone(obj[key], weakMap); | ||
} | ||
} | ||
return o; | ||
} | ||
|
||
export default function deepMerge(a, b) { | ||
if (getType(a) !== '[object Object]' && getType(a) !== '[object Array]') { | ||
return deepClone(b); | ||
} | ||
|
||
const isArray = getType(a) === '[object Array]'; | ||
const res = isArray ? [] : {}; | ||
for (const key in b) { | ||
if (b.hasOwnProperty(key)) { | ||
res[key] = deepMerge(a[key], b[key]); | ||
} | ||
} | ||
for (const key in a) { | ||
if (res[key] === undefined && a.hasOwnProperty(key)) { | ||
res[key] = deepClone(a[key]); | ||
} | ||
} | ||
return res; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
对象合并 | ||
|
||
深度合并两个对象, 并且修改新对象不会影响原对象, 相同的属性则以 b 对象为主 | ||
|
||
用例 1: | ||
|
||
```js | ||
const a = { a: 1 }; | ||
const b = { b: 2 }; | ||
|
||
deepMerge(a, b); // { a: 1, b: 2 } | ||
``` | ||
|
||
用例 2: | ||
|
||
```js | ||
const a = { foo: { bar: 0 }, arr: [1, 3, { a: { b: 1 } }] }; | ||
const b = { foo: { bar: 1 }, arr: [1, 2, { b: { a: 1 } }] }; | ||
|
||
deepMerge(a, b); // { foo: { bar: 1 }, arr: [1, 2, { a: { b: 1 }, b: { a: 1 } }] } | ||
``` | ||
|
||
用例 3: | ||
|
||
b 属性值为 undefined 不会并入 a | ||
|
||
```js | ||
const a = { a: 1 }; | ||
const b = { a: undefined }; | ||
|
||
deepMerge(a, b); // { a: 1 } | ||
``` | ||
|
||
用例 4: | ||
|
||
```js | ||
const a = { a: 1 }; | ||
const b = undefined; | ||
|
||
deepMerge(a, b); // { a: 1 } | ||
``` | ||
|
||
用例 5: | ||
|
||
```js | ||
const a = undefined; | ||
const b = { a: 1 }; | ||
|
||
deepMerge(a, b); // { a: 1 } | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/** | ||
* 对象合并 | ||
* | ||
* @export | ||
* @param {Object} a | ||
* @param {Object} b | ||
* @return {Object} | ||
*/ | ||
export default function deepMerge(a, b) { | ||
return {}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import f from './index.mjs'; | ||
import { it } from 'mocha'; | ||
import { assert } from 'chai'; | ||
|
||
it('一层对象: 输入 { a: 1 }, { b: 2 }', () => { | ||
assert.deepEqual(f({ a: 1 }, { b: 2 }), { a: 1, b: 2 }); | ||
}); | ||
|
||
it('两层对象: 输入 { a: 1, b: { c: 2 } }, { b: 2 }', () => { | ||
assert.deepEqual(f({ a: 1, b: { c: 2 } }, { b: { c: 3, d: 4 } }), { | ||
a: 1, | ||
b: { c: 3, d: 4 }, | ||
}); | ||
}); | ||
|
||
it("两层对象存在数组合并: 输入 { b: { c: [1, 3, { a: 1 }] } }, { b: { c: ['1', 2, { a: 2 }] } }", () => { | ||
assert.deepEqual( | ||
f({ b: { c: [1, 3, { a: 1 }] } }, { b: { c: ['1', 2, { a: 2 }] } }), | ||
{ b: { c: ['1', 2, { a: 2 }] } } | ||
); | ||
}); | ||
|
||
it('b 中属性值为 undefined 时不会合并: 输入 { a: 1 }, { a: undefined }', () => { | ||
assert.deepEqual(f({ a: 1 }, { a: undefined }), { a: 1 }); | ||
}); | ||
|
||
it('边界输入一 undefined | null, { a: 1 }', () => { | ||
assert.deepEqual(f(undefined, { a: 1 }), { a: 1 }); | ||
assert.deepEqual(f(null, { a: 1 }), { a: 1 }); | ||
}); | ||
|
||
it('边界输入二 { a: 1 }, undefined | null', () => { | ||
assert.deepEqual(f({ a: 1 }, undefined), { a: 1 }); | ||
assert.deepEqual(f({ a: 1 }, null), { a: 1 }); | ||
}); |
Large diffs are not rendered by default.
Oops, something went wrong.