【问题标题】:How can I merge 2 javascript objects, populating the properties in one if they don't exist in the other?如何合并 2 个 javascript 对象,如果属性不存在于另一个对象中,则将其填充到一个对象中?
【发布时间】:2010-10-28 02:50:27
【问题描述】:

如果我有一个 javascript 对象/关联。数组定义如下:

function somefunction(options) {

    var defaults = {
        prop1: 'foo',
        prop2: 'bar'
    };

    //Do stuff here

}

我想用这个作为函数的默认值。所以当函数被调用时,我想用defaults 中的值填充options 变量,但前提是它们在options 中不存在。

所以可以说这是被称为

somefunction({ prop1: 'fish' });

我怎样才能让optionsdefaults 合并,这样我才能得到这个

{
    prop1: 'fish',
    prop2: 'bar'
}

【问题讨论】:

    标签: javascript arrays merge


    【解决方案1】:

    重新阅读问题后,我意识到您可能正在寻找更像这样的东西:

    var a = { 'foo': 'bar', 'baz': 'bat' };
    var b = { 'foo': 'quux' };
    for (var prop in a) {
        if (prop in b) { continue; }
        b[prop] = a[prop];
    }
    

    【讨论】:

      【解决方案2】:

      您可以查看 jQuery 或 Prototypes extend 功能。

      看起来像这样:(直接取自 jQuery)

      jQuery.extend = jQuery.fn.extend = function() {
          // copy reference to target object
          var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
      
          // Handle a deep copy situation
          if ( typeof target === "boolean" ) {
              deep = target;
              target = arguments[1] || {};
              // skip the boolean and the target
              i = 2;
          }
      
          // Handle case when target is a string or something (possible in deep copy)
          if ( typeof target !== "object" && !jQuery.isFunction(target) )
              target = {};
      
          // extend jQuery itself if only one argument is passed
          if ( length == i ) {
              target = this;
              --i;
          }
      
          for ( ; i < length; i++ )
              // Only deal with non-null/undefined values
              if ( (options = arguments[ i ]) != null )
                  // Extend the base object
                  for ( var name in options ) {
                      var src = target[ name ], copy = options[ name ];
      
                      // Prevent never-ending loop
                      if ( target === copy )
                          continue;
      
                      // Recurse if we're merging object values
                      if ( deep && copy && typeof copy === "object" && !copy.nodeType )
                          target[ name ] = jQuery.extend( deep, 
                              // Never move original objects, clone them
                              src || ( copy.length != null ? [ ] : { } )
                          , copy );
      
                      // Don't bring in undefined values
                      else if ( copy !== undefined )
                          target[ name ] = copy;
      
                  }
      
          // Return the modified object
          return target;
      };
      

      【讨论】:

      • 执行一些深拷贝魔法似乎需要做很多工作——真的有必要吗?
      • 这是一个很好的问题,深拷贝的东西可能有点矫枉过正。
      • 这不是你需要写的代码,这就是extend函数的样子,我所要做的就是options = $.extend(defaults, options)
      • 我意识到他正在共享一个 jQuery 方法 - 但它会执行大量处理来执行“深度复制”,而 OP 让它看起来比这更简单。只是要记住的事情。
      • 我想覆盖 Flot 选项(它比一层更深),我需要深拷贝,所以很高兴有人提到它。
      【解决方案3】:

      我是 PrototypeJS 的坚持者。我们的 Java 类型比 jQuery 更喜欢 PrototypeJS 的 OO 设计。下面是如何将两个 Object/Hash/Maps 与 Proto 合并:

      $H(obj1).merge(obj2).toObject()
      

      输入 obj1 和 obj2 不受影响。 obj2 映射条目具有优先级(即 obj1 和 obj2 都具有相同的键,obj2 中该键的值将被覆盖)。

      【讨论】:

      • 对你有好处。你最好问问那些认为它更容易理解的人。我只是告诉那些希望用 PrototypeJS 做的人如何用 PrototypeJS 做。除了巨魔之外,这里没有任何相关性,但我喜欢 JQuery 用于列表操作。不幸的是,您总是必须使用列表运算符,而我最常想对简单的标量对象进行操作。
      【解决方案4】:
      <html>
      <head> 
      <title>Testing</title>
      
      <script type="text/JavaScript">
      // The method is simpler than its demonstration:
      
      function merge(obj1, obj2, force){
          for(var p in obj2){
              if(force || obj1[p]=== undefined) obj1[p]= obj2[p];
          }
          return obj1;
      }
      
      // demo:
      var merge_demo= function(){
          // set up a to string method, just for the demo
          var restring= function(){
              var s= [];
              for(var p in this){
                  s[s.length]= p+': '+this[p];
              }
              return '{ '+s.join(', ')+' }';
          }
          // define two objects
          var O1={
              a: 1, b: 2, c: 3
          }
          var O2={
              a: 10, b: 11, d: 4
          }
          // Begin demo, write the object contents to a string:
          var str= 'Object1='+restring.call(O1)+'\nObject2='+restring.call(O2)+'\n\n';
      
          //merge the two objects without overwriting values: 
          merge(O1, O2);
      
          // Update object contents in string:
          str+= 'merge(Object1,Object2)='+restring.call(O1)+'\n\n';
      
          //merge and replace existing values:
          merge(O1, O2, true);
      
          // Update and return string: 
          str+= 'merge(Object1,Object2,true)='+restring.call(O1);
          return str;
      }
      alert(merge_demo());
      </script>
      </head>
      
      <body>
      </body>
      </html>
      

      【讨论】:

        【解决方案5】:

        使用 Google Closure Library 可以这样做:

        goog.require('goog.object');
        function somefunction(options) {
          var defaults = {
            prop1: 'foo',
            prop2: 'bar'
          };
          goog.object.extend(defaults, options);
          // if the property is defined in options it will overwrite value.
        }
        

        【讨论】:

          猜你喜欢
          • 2016-09-14
          • 2022-11-19
          • 1970-01-01
          • 2019-11-18
          • 2017-06-11
          • 1970-01-01
          • 2016-07-18
          • 2019-04-27
          • 2020-11-16
          相关资源
          最近更新 更多