从头开始
Ramba 库中的新功能意味着您不必自己执行此操作,但如果维护人员从不使用它怎么办?当您现在需要某项功能或行为时,您不希望等待其他人编写您的代码。
下面,我们实现自己的递归merge
const isObject = x =>
Object (x) === x
const merge = (left = {}, right = {}) =>
Object.entries (right)
.reduce
( (acc, [ k, v ]) =>
isObject (v) && isObject (left [k])
? { ...acc, [k]: merge (left [k], v) }
: { ...acc, [k]: v }
, left
)
我们的合并函数也可以通用并接受任何两个对象作为输入。
const x =
{ a: 1, b: 1, c: 1 }
const y =
{ b: 2, d: 2 }
console.log (merge (x, y))
// { a: 1, b: 2, c: 1, d: 2 }
如果每个对象都包含一个属性,其值也是一个对象,merge 将递归并合并嵌套的对象。
const x =
{ a: { b: { c: 1, d: 1 } } }
const y =
{ a: { b: { c: 2, e: 2 } }, f: 2 }
console.log (merge (x, y))
// { a: { b: { c: 2, d: 1, e: 2 } }, f: 2 }
数组也是人
为了支持merge 中的数组,我们引入了一个突变助手mut,它将[ key, value ] 对分配给给定对象o。数组也被视为对象,因此我们可以使用相同的mut 函数来更新数组和对象
注意,Ramda 的合并函数不会尝试合并数组。编写自己的函数的主要优点是您可以轻松地增强它们的行为以满足程序不断发展的需求。
const mut = (o, [ k, v ]) =>
(o [k] = v, o)
const merge = (left = {}, right = {}) =>
Object.entries (right)
.map
( ([ k, v ]) =>
isObject (v) && isObject (left [k])
? [ k, merge (left [k], v) ]
: [ k, v ]
)
.reduce (mut, left)
浅合并按预期工作
const x =
[ 1, 2, 3, 4, 5 ]
const y =
[ 0, 0, 0 ]
const z =
[ , , , , , 6 ]
console.log (merge (x, y))
// [ 0, 0, 0, 4, 5 ]
console.log (merge (y, z))
// [ 0, 0, 0, <2 empty items>, 6 ]
console.log (merge (x, z))
// [ 1, 2, 3, 4, 5, 6 ]
还有深度合并
const x =
{ a: [ { b: 1 }, { c: 1 } ] }
const y =
{ a: [ { d: 2 }, { c: 2 }, { e: 2 } ] }
console.log (merge (x, y))
// { a: [ { b: 1, d: 2 }, { c: 2 }, { e: 2 } ] }
可变参数合并
也许我们想要一个不限于两个输入的合并函数; mergeAll
const Empty =
{}
const mergeAll = (first = Empty, ...rest) =>
first === Empty
? first
: merge (first, mergeAll (...rest))
mergeAll ({ a: 1 }, { b: 2 }, { c: 3 })
// { a: 1, b: 2, c: 3 }
此答案摘自另一个问题:How to compare two objects and get key-value pairs of their differences?