合并对象(关联数组)


147

在JavaScript中合并两个关联数组的最佳/标准方式是什么?每个人都只是通过滚动自己的for循环来做到这一点吗?


10
javascript btw中没有关联数组,只有对象。
gblazex

在Perl中交叉引用相同的问题:stackoverflow.com/questions/350018/…–
dreftymac

Answers:


204

用jquery可以打电话 $.extend

var obj1 = {a: 1, b: 2};
var obj2 = {a: 4, c: 110};

var obj3 = $.extend(obj1, obj2); 

obj1 == obj3 == {a: 4, b: 2, c: 110} // Pseudo JS

(关联数组是js中的对象)

看这里:http : //api.jquery.com/jQuery.extend/


编辑:像rymo建议的那样,最好这样做:

obj3 = $.extend({}, obj1, obj2); 
obj3 == {a: 4, b: 2, c: 110}

此处obj1(和obj2)保持不变。


edit2:在2018年,方法是通过Object.assign

var obj3 = Object.assign({}, obj1, obj2); 
obj3 === {a: 4, b: 2, c: 110} // Pseudo JS

如果使用ES6,可以使用Spread运算符实现:

const obj3 = { ...obj1, ...obj2 };

54
或为避免污损obj1,请使用一个空对象作为目标:$.extend({}, obj1, obj2)
rymo 2012年

是的,在处理闭包和通过引用传递的对象时,请遵循rymo的建议,以免影响后续操作的原始对象。
内森·史密斯

2
对于现代浏览器,使用@manfred使用来检查解决方案,Object.assign()如果您尚未使用该库,则该解决方案不依赖JQuery。
菲尔(Phil)

它可以工作,但是会更改第一个参数,这是您需要注意的。请参阅developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/…–
kulpae,

62

现在在2016年,我会说最好/标准的方法是Object.assign()
Pure Javascript。不需要jQuery。

obj1 = {a: 1, b: 2};
obj2 = {a: 4, c: 110};
obj3 = Object.assign({},obj1, obj2);  // Object {a: 4, b: 2, c: 110}

此处提供了更多信息,示例和polyfill:https :
//developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign


obj3的类型是什么?如果obj1是IABC类型该怎么办,obj3之后会保留该类型吗?
windmaomao

49

这是原型的工作方式:

Object.extend = function(destination, source) {
    for (var property in source) {
        if (source.hasOwnProperty(property)) {
            destination[property] = source[property];
        }
    }
    return destination;
};

称为,例如:

var arr1 = { robert: "bobby", john: "jack" };
var arr2 = { elizabeth: "liz", jennifer: "jen" };

var shortnames = Object.extend(arr1,arr2);

编辑:添加了hasOwnProperty()检查,如bucabay在注释中正确指出的


6
您将需要测试source.hasOwnProperty(property)以确保仅复制立即属性。照
原样

22

把事情简单化...

function mergeArray(array1,array2) {
  for(item in array1) {
    array2[item] = array1[item];
  }
  return array2;
}

6
您检查hasOwnProperty以避免在arrau1.prototype
LeeGee 2014年

@LeeGee是正确的。你需要那张hasOwnProperty支票。将对象称为数组也具有误导性(它们是对象),arg名称应表示array2发生了变异,或者应返回新对象。我会编辑答案,但实际上,它几乎变成了乔纳森·芬德兰(Jonathan Fingland)编辑的答案,该答案已经得到纠正。
瓦兹(Vaz)

14

下划线还具有扩展方法:

将源对象中的所有属性复制到目标对象。它是有序的,因此最后一个源将覆盖先前参数中的同名属性。

_.extend(destination, *sources) 

_.extend({name : 'moe'}, {age : 50});
=> {name : 'moe', age : 50}


6

如果名称相同但值不同,是否要覆盖属性?

您是否要永久更改其中一个原始对象,

还是要返回一个新的合并对象?

function mergedObject(obj1, obj2, force){
    for(var p in obj1) this[p]= obj1[p];
    for(var p in obj2){
        if(obj2.hasOwnProperty(p)){
            if(force || this[p]=== undefined) this[p]= obj2[p];
            else{
                n= 2;
                while(this[p+n]!== undefined)++n;
                this[p+n]= obj2[p];
            }
        }
    }
}

6

滚动自己的扩展/混合功能

function extend(objects) {
    var args
        , first = Array.prototype.slice.call(arguments, 0, 1)[0]
        , second;

    if (arguments.length > 1) {
        second = Array.prototype.splice.call(arguments, 1, 1)[0];
        for (var key in second) {
            first[key] = second[key];
        }
        args = Array.prototype.slice.call(arguments, 0);
        return extend.apply(this, args);
    }

    return first;
}

...

var briansDirections = {
    step1: 'Remove pastry from wrapper.',
    step2: 'Place pastry toaster.',
    step3: 'Remove pastry from toaster and enjoy.',
};
extend(briansDirections, { step1: 'Toast Poptarts' }, { step2: 'Go ahead, toast \'em' }, { step3: 'Hey, are you sill reading this???' });

...

这只是延伸的图示的对象,递归。另外,请注意,此递归函数是TCO(优化尾调用),因为它的返回是对自身的最后一次调用。

此外,您可能需要有针对性的属性。在这种情况下,你可能要凝聚基于对象idquantity或其他财产。这种方法可能有一本关于它的小书,并且需要对象并置,并且可能变得非常复杂。我已经为此编写了一个小型库,可根据要求提供。

希望这可以帮助!


4
  1. 在Javascript中,没有关联数组的概念,有对象
  2. 合并两个对象的唯一方法是循环其属性,并将指针复制到非原始类型的值,并将原始类型的值复制到另一个实例

8
Javascript中的对象是作为关联数组实现的,因此肯定有相同的概念
Dexygen

2

在2019年,您有2个不错的选择:

对象分配 [ doc ]

const result = Object.assign({}, baseObject, updatingObject);

对象传播 [ doc ]

const result = { ...baseObject, ...updatingObject};

第一个趋向于更安全,更标准和多价。这里的优点和缺点



1

jQuery具有用于深度复制的布尔值。您可以这样做:

MergeRecursive = function(arr1, arr2){
    $.extend(true, arr1, arr2);
    return arr1;                
};

您也可以编辑此函数以支持n数组合并。

ArrayMergeRecursive = function(){
     if(arguments.length < 2){
          throw new Error("ArrayMergeRecursive: Please enter two or more objects to merge!");
     }

    var arr1=arguments[0];
    for(var i=0; i<=arguments.length; i++ ){
        $.extend(true, arr1, arguments[i]);                 
    }

    return arr1;                
};

所以现在你可以做

var arr1 = {'color': {'mycolor': 'red'}, 3: 5},
    arr2 = {4: 10, 'color': {'favorite': 'green', 0: 'blue'}},
    arr3 = ['Peter','Jhon','Demosthenes'],
    results = ArrayMergeRecursive(arr1, arr2, arr3); // (arr1, arr2 ... arrN)
console.log("Result is:", results);

0

我需要一个深层对象合并。因此,所有其他答案对我没有太大帮助。_.extend和jQuery.extend效果很好,除非您像我一样有一个递归数组。但这还不错,您可以在五分钟内对其进行编程:

var deep_merge = function (arr1, arr2) {
    jQuery.each(arr2, function (index, element) {
        if (typeof arr1[index] === "object" && typeof element === "object") {
            arr1[index] = deep_merge(arr1[index], element);
        } else if (typeof arr1[index] === "array" && typeof element === "array") {
            arr1[index] = arr1[index].concat(element);
        } else {
            arr1[index] = element;
        }
    });
    return arr1;
}

0

要在jQuery中合并数组,$。merge怎么办?

var merged = $.merge([{id:3, value:'foo3'}], [{id:1, value:'foo1'}, {id:2, value:'foo2'}]);
merged[0].id == 3;
merged[0].value == 'foo3';
merged[1].id == 1;
merged[1].value == 'foo1';
merged[2].id == 2;
merged[2].value == 'foo2';

0

递归解决方案(也扩展对象的数组)+空检查

var addProps = function (original, props) {
    if(!props) {
        return original;
    }
    if (Array.isArray(original)) {
        original.map(function (e) {
            return addProps(e, props)
        });
        return original;
    }
    if (!original) {
        original = {};
    }
    for (var property in props) {
        if (props.hasOwnProperty(property)) {
            original[property] = props[property];
        }
    }
    return original;
};

测验

console.log(addProps([{a: 2}, {z: 'ciao'}], {timestamp: 13}));
console.log(addProps({single: true}, {timestamp: 13}));
console.log(addProps({}, {timestamp: 13}));
console.log(addProps(null, {timestamp: 13}));

[ { a: 2, timestamp: 13 }, { z: 'ciao', timestamp: 13 } ]
{ single: true, timestamp: 13 }
{ timestamp: 13 }
{ timestamp: 13 }

我尝试将其与Node JS结合使用,但Object.getOwnPropertyNames is not a function会使应用崩溃。
Legoless

我在plv8 PostgreSQL扩展中使用了一些老式的v8引擎。它可以在浏览器中使用。只需在您的JS引擎中找到一种方法即可完成与“ hasOwnProperty”相同的操作。然后,您可以重用此逻辑。
sscarduzio

0

这是最好的解决方案。

obj1.unshift.apply( obj1, obj2 );

而且,obj1可以在循环内增长而没有任何问题。(可以说obj2是动态的)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.