问两个深层对象如何替换合并?

451 阅读2分钟

问两个深层对象如何替换合并?

总所周知JavaScript中的对象合并就很简单了,可以使用Object.assign() 这种方法进行合并,还可以使用... 对象拓展运算符进行拓展。数组可以使用Array.prototype.concat() 数组合并又或者使用... 数组拓展运算符 进行合并,但往往这些只能合并简单的类型数据,对于合并深层的数据类型比如嵌套对象如何进行合并?对于数组对象合并就不再说了,那么如何替换呢,对象浅一点的对象可以进行覆盖,数组对象却不能,那么对于深层的对象或者数组对象如何替换呢?

解决方案

代码实现

  • 使用loadsh中的merge方法
_.merge(object, [sources])

该方法类似_.assign, 除了它递归合并 sources 来源对象自身和继承的可枚举属性到 object 目标对象。如果目标值存在,被解析为undefinedsources 来源对象属性将被跳过。数组和普通对象会递归合并,其他对象和值会被直接分配覆盖。源对象从从左到右分配。后续的来源对象属性会覆盖之前分配的属性。

Note: 这方法会改变对象 object.

添加版本

0.5.0

参数

  1. object (Object) : 目标对象。
  2. [sources] (...Object) : 来源对象。

返回

(Object) : 返回 object.

var object = {
  'a': [{ 'b': 2 }, { 'd': 4 }]
};
 
var other = {
  'a': [{ 'c': 3 }, { 'e': 5 }]
};
 
_.merge(object, other);
// => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
  • 自定义一个hooks工具类函数
/**
 * Simple object check.
 * @param item
 * @returns {boolean}
 */
// 判断对应的类型
export function typeChecked(arg: any) {
  const len = Object.prototype.toString.call(arg).substring(8).split('').length
  return Object.prototype.toString.call(arg).substring(8).split('').slice(0, len - 1).join('')
}
​
/**
 * Deep merge two objects.
 * @param target
 * @param ...sources
 */
export function mergeDeep(target, ...sources) {
  if (!sources.length) return target;
  const source = sources.shift();
​
  if (typeChecked(target)==='Object' && typeChecked(source)==='Object') {
    for (const key in source) {
      if (typeChecked(source[key])==='Object') {
        if (!target[key]) Object.assign(target, { [key]: {} });
        mergeDeep(target[key], source[key]);
      } else {
        Object.assign(target, { [key]: source[key] });
      }
    }
  }
​
  return mergeDeep(target, ...sources);
}
mergeDeep(this, { a: { b: { c: 123 } } });
// or
const merged = mergeDeep({a: 1}, { b : { c: { d: { e: 12345}}}});  
console.dir(merged); // { a: 1, b: { c: { d: [Object] } } }

总结

世上无难事,只要肯放弃,加油你还年轻!!!