【问题标题】:Merge two objects with override in javascript [duplicate]在javascript中使用覆盖合并两个对象[重复]
【发布时间】:2018-05-04 17:59:19
【问题描述】:

我想合并两个对象,覆盖属性但保留未被覆盖的属性。

示例:我有以下对象

const theme = {
 colors: {
  base: '#fff',
  accent: '#ff0000'
 }
}

const themeOverride = {
 colors: {
  accent: '#ff8900'
 }
}

并希望将这些合并在一起以获得

const newTheme = {
  colors: {
   base: '#fff',
   accent: '#ff8900'
  }
}

【问题讨论】:

    标签: javascript javascript-objects


    【解决方案1】:

    JS 没有内置的方法来做到这一点,但是用 Lodash 或者 Underscore 的 _.merge() 或 Ramda 的 _.mergeDeepLeft() 都非常简单,所有这些都递归合并对象。

    const theme = {
     colors: {
      base: '#fff',
      accent: '#ff0000'
     }
    }
    
    const themeOverride = {
     colors: {
      accent: '#ff8900'
     }
    }
    
    const newTheme = _.merge(theme, themeOverride);
    
    console.log(newTheme);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

    【讨论】:

    • 有点好奇为什么这会得到如此多的反对。
    • 赞成只是因为我认为反对票不合法。您正在回答 OP 问题并公平地解释您的观点。祝您有美好的一天,感谢您的贡献。
    【解决方案2】:

    如果只想合并theme和themeOverride的属性color,可以通过下面的代码实现:

    var theme = {
     colors: {
      base: '#fff',
      accent: '#ff0000'
     }
    };
    var themeOverride = {
     colors: {
      accent: '#ff8900'
     }
    };
    Object.assign(theme.colors, themeOverride.colors);
    console.log(theme);

    【讨论】:

    • 虽然这回答了问题中的具体示例,但在更广泛的意义上它并没有真正的帮助,因为该示例被称为 themecolors,假设会有也需要合并的其他子属性(例如fontsborders 等)。
    【解决方案3】:

    您可以使用Object.assign 来合并这些对象

    更新现有对象

    const theme = {
      colors: {
        base: '#fff',
        accent: '#ff0000'
      }
    }
    
    const themeOverride = {
      colors: {
        accent: '#ff8900'
      }
    }
    
    Object.assign(theme.colors, themeOverride.colors)
    
    console.log(theme)

    或者创建新对象

    const theme = {
      colors: {
        base: '#fff',
        accent: '#ff0000'
      }
    }
    
    const themeOverride = {
      colors: {
        accent: '#ff8900'
      }
    }
    
    newTheme = { colors: Object.assign({}, theme.colors, themeOverride.colors) }
    
    console.log(newTheme)

    【讨论】:

    • 也许你想要Object.assign({}, theme.colors, themeOverride.colors)
    • Object.assign({}, theme.colors, themeOverride.colors) -> {"base": "#fff", "accent": "#ff8900"}。但它会是新对象,对吧。
    【解决方案4】:

    您可以使用 reduce 和旧的 theme 作为初始值。试试这样的:

    const theme = {
      colors: {
        base: '#fff',
        accent: '#ff0000'
      },
    }
    
    const themeOverride = {
      colors: {
        accent: '#ff8900'
      },
      border: {
        borderWidth: '2px'
      }
    }
    
    const newTheme = Object.keys(themeOverride).reduce((prev, key) => {
      prev[key] = Object.assign({}, theme[key] || {}, themeOverride[key])
      return prev
    }, Object.assign({}, theme))
    
    console.log(newTheme)

    请注意,此解决方案需要最多 2 级嵌套。

    【讨论】:

      【解决方案5】:

      迭代两个对象,寻找交集并在该实例中覆盖;否则,直接复制即可;

      const theme = {
       colors: {
        base: '#fff',
        accent: '#ff0000'
       }
      }
      
      const themeOverride = {
       colors: {
        accent: '#ff8900'
       }
      }
      window.onload = mergeObjects(theme,themeOverride)
      
      function mergeObjects(base,override) {
         var mergedObj = {'colors' : {}};
         for(key in base["colors"]) {
            if(override['colors'][key] == undefined) {
              mergedObj['colors'][key] = base['colors'][key]
            }
            else {
              mergedObj['colors'][key] = override['colors'][key]
            }
         }
         console.log('mergedObject is',mergedObj)
      }

      【讨论】:

        【解决方案6】:

        您可以通过迭代所有属性以使用对象的递归方法进行更新来合并。

        function merge(target, source) {
            Object.keys(source).forEach(function (key) {
                if (source[key] && typeof source[key] === 'object') {
                    merge(target[key] = target[key] || {}, source[key]);
                    return;
                }
                target[key] = source[key];
            });
        }
        
        var theme = { colors: { base: '#fff', accent: '#ff0000' } }, 
            themeOverride = { colors: { accent: '#ff8900' } };
            
        merge(theme, themeOverride);
        
        console.log(theme);

        【讨论】:

          【解决方案7】:

          您可以递归地查看您的对象并以这种方式分配新的更新值。

          在这里,我为它做了一个函数:

          const theme = {
           colors: {
            base: '#fff',
            accent: '#ff0000'
           }
          }
          
          const themeOverride = {
           colors: {
            accent: '#ff8900'
           }
          }
          
          function overrideObject(o1,o2){
            var res = {};
            //Go through all your attributes
            for (var a in o1){
              //Begin recursive method if another object is detected
              if(typeof o1[a] == 'object'){
                res[a] = overrideObject(o1[a],o2[a])
              }
              //Clone old data & update it if necessary
              else{
                res[a] = o1[a]; 
                if(typeof o2[a] != 'undefined') res[a] = o2[a]; 
              }
            }
            
            return res;
          }
          
          console.log(overrideObject(theme,themeOverride));

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-01-02
            • 2018-05-13
            • 2019-10-04
            • 1970-01-01
            • 2017-09-22
            • 2021-07-01
            • 2015-04-06
            • 2018-06-25
            相关资源
            最近更新 更多