每天一点前端知识 - 合并数据

137 阅读1分钟

实现

const merge = (target, ...extend) => {
  const handleMerge = isArray(target) ? mergeArr : mergeObj;
  extend.map(item => (target = handleMerge(target, item)));
  return target;
};

const mergeArr = (base, extend, key = 'id') => {
  if (!isArray(base)) {
    return extend;
  }
  if (!isArray(extend)) {
    return base;
  }
  const sameItems = {};
  [...base, ...extend].map(item => {
    const idKey = isObject(item) ? item[key] ?? JSON.stringify(item) : item;
    if (sameItems[idKey] === undefined) {
      sameItems[idKey] = item;
    } else {
      const oldItem = sameItems[idKey];
      if (isObject(oldItem) && isObject(item)) {
        sameItems[idKey] = mergeObj(oldItem, item, key);
      } else if (isArray(oldItem) && isArray(item)) {
        sameItems[idKey] = mergeArr(oldItem, item, key);
      } else {
        sameItems[idKey] = item;
      }
    }
  });
  return Object.keys(sameItems).map(v => sameItems[v]);
};

const mergeObj = (base, extend, key = 'id') => {
  if (!isObject(base)) {
    return extend;
  }
  if (!isObject(extend)) {
    return base;
  }
  for (let k in extend) {
    if (hasProp(extend, k)) {
      if (isObject(base[k]) && isObject(extend[k])) {
        base[k] = mergeObj(base[k], extend[k], key);
      } else if (isArray(base[k]) && isArray(extend[k])) {
        base[k] = mergeArr(base[k], extend[k], key);
      } else {
        base[k] = extend[k];
      }
    } else {
      Object.setPrototypeOf(base, {[k]: extend[k]});
    }
  }
  return base;
};

使用

merge(target, ...extend);


示例

const a = {
  num: 12,
  str: 'hello',
  nul: null,
  arr: [
    {
      name: 'a1',
      children: [1, 'hi'],
    },
  ],
  obj: {
    name: 'obj',
    age: 22,
    oa1: [2, null, 'oa1'],
    oa2: {
      name: 'test',
    },
  },
};

const b = {
  num: 22,
  arr: [
    {
      children: [3],
    },
  ],
  obj: {
    oa2: {
      age: 30,
    },
  },
  obj2: {
    data: [1, 2, 3],
  },
};

const c = [
  {
    test: 123,
  },
];

merge(a, b, c, {str: 'ihuxy'});

10.png

10-result.png

演示地址:ihuxy.com/play?utils=…