如何合并 2 个 javascript 对象,如果属性不存在于另一个对象中,则将其填充到一个对象中?

Posted

技术标签:

【中文标题】如何合并 2 个 javascript 对象,如果属性不存在于另一个对象中,则将其填充到一个对象中?【英文标题】:How can I merge 2 javascript objects, populating the properties in one if they don't exist in the other? 【发布时间】: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'

【问题讨论】:

【参考方案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.

【讨论】:

以上是关于如何合并 2 个 javascript 对象,如果属性不存在于另一个对象中,则将其填充到一个对象中?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JavaScript 中将两个对象合并到同一个属性中?

如果某些对象彼此不兼容,如何对对象进行分组和合并?

如何合并嵌套对象Javascript? [复制]

如何比较2个长度数组的对象条目的属性并合并为一个? [复制]

在 Javascript 中合并 2 个数据表

如何使用 jq 合并来自 2 个文件的 2 个 JSON 对象?