首页 > 解决方案 > Javascript 简单对象默认覆盖

问题描述

bsd

我有一个简单的对象,我想用另一个对象覆盖它,如果对象中不存在某些属性,它应该取自默认预设对象,可能是深度嵌套的

这是默认设置对象的示例

defaults = {
   name : 'Joe',
   options : {
      color : 'green',
      dates : {
         from : new Date,
         to   : new Date,
      }
   }
}

这是提供的对象

settings = {
   name : 'David',
   options : {
      color : 'purple'
   }
}

这是预期的结果,两者之间的组合......

final = {
   name : 'David',
   options : {
      color : 'purple',
      dates : {
         from : new Date,
         to   : new Date,
      }
   }
}

有没有一种简单的方法可以在不使用任何外部库的情况下实现这一目标?我已经尝试了一些方法(JSON.stringify / parse/ 迭代对象 / 等等......)但无法得到一个干净的解决方案......希望是一个单线器

任何帮助将非常感激...

标签: javascriptperformance

解决方案


这是我的贡献。

shallow需要注意的是,由于对象的性质和deep复制,代码相当冗长。

使用Object.assign(defaults, settings), 将合并您的对象,但您的date密钥将在执行对象的浅拷贝时被删除。

下面,我使用了How to deep merge instead of shallow merge?一个名为的用户找到的片段,该片段jhildenbiddle执行deep对象的合并并且是immutable(不编辑原始数组)。


let defaults = {
  name: 'Joe',
  options: {
    color: 'green',
    dates: {
      from: new Date(),
      to: new Date(),
    }
  }
};

let settings = {
  name: 'David',
  options: {
    color: 'purple'
  }
};

function mergeDeep(...objects) {
  const isObject = obj => obj && typeof obj === 'object';

  return objects.reduce((prev, obj) => {
    Object.keys(obj).forEach(key => {
      const pVal = prev[key];
      const oVal = obj[key];

      if (Array.isArray(pVal) && Array.isArray(oVal)) {
        prev[key] = pVal.concat(...oVal);
      } else if (isObject(pVal) && isObject(oVal)) {
        prev[key] = mergeDeep(pVal, oVal);
      } else {
        prev[key] = oVal;
      }
    });

    return prev;
  }, {});
}

let final = mergeDeep(defaults, settings);

console.log(final);


推荐阅读