[英]Merging objects (associative arrays)
What's the best/standard way of merging two associative arrays in JavaScript? 在JavaScript中合并两个关联数组的最佳/标准方法是什么? Does everyone just do it by rolling their own
for
loop? 每个人都只是通过滚动自己
for
循环来做到这一点吗?
with jquery you can call $.extend
使用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
(assoc. arrays are objects in js) (assoc。数组是js中的对象)
look here: http://api.jquery.com/jQuery.extend/ 看这里: http : //api.jquery.com/jQuery.extend/
edit: Like rymo suggested, it's better to do it this way: 编辑:像rymo建议的那样,最好这样做:
obj3 = $.extend({}, obj1, obj2);
obj3 == {a: 4, b: 2, c: 110}
As here obj1 (and obj2) remain unchanged. 因为这里obj1(和obj2)保持不变。
edit2: In 2018 the way to do it is via Object.assign
: edit2:在2018年,这样做的方法是通过
Object.assign
:
var obj3 = Object.assign({}, obj1, obj2);
obj3 === {a: 4, b: 2, c: 110} // Pseudo JS
If working with ES6 this can be achieved with the Spread Operator : 如果使用ES6,可以使用Spread Operator实现:
const obj3 = { ...obj1, ...obj2 };
Now in 2016 I would say the best/standard way is Object.assign() 现在在2016年我会说最好的/标准的方式是Object.assign()
Pure Javascript. 纯Javascript。 No jQuery is needed.
不需要jQuery。
obj1 = {a: 1, b: 2};
obj2 = {a: 4, c: 110};
obj3 = Object.assign({},obj1, obj2); // Object {a: 4, b: 2, c: 110}
More information, examples and polyfill here: 更多信息,示例和polyfill:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
This is how Prototype does it: 这就是Prototype的作用:
Object.extend = function(destination, source) {
for (var property in source) {
if (source.hasOwnProperty(property)) {
destination[property] = source[property];
}
}
return destination;
};
called as, for example: 被称为,例如:
var arr1 = { robert: "bobby", john: "jack" };
var arr2 = { elizabeth: "liz", jennifer: "jen" };
var shortnames = Object.extend(arr1,arr2);
EDIT : added hasOwnProperty() check as correctly pointed out by bucabay in comments 编辑 :添加hasOwnProperty()检查正确由bucabay在评论中指出
Keep it simple... 把事情简单化...
function mergeArray(array1,array2) {
for(item in array1) {
array2[item] = array1[item];
}
return array2;
}
Underscore also has an extend method: Underscore也有一个扩展方法:
Copy all of the properties in the source objects over to the destination object.
将源对象中的所有属性复制到目标对象。 It's in-order, so the last source will override properties of the same name in previous arguments.
它是有序的,因此最后一个源将覆盖先前参数中相同名称的属性。
_.extend(destination, *sources)
_.extend({name : 'moe'}, {age : 50});
=> {name : 'moe', age : 50}
在dojo中 ,2对象/数组“merge”将是lang.mixin(destination, source)
- 您还可以将多个源混合到一个目标等中 - 有关详细信息,请参阅mixin函数的参考 。
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???' });
... ...
This simply extends a splat of objects, recursively. 这仅仅简单地扩展对象的图示 ,递归。 Also, note that this recursive function is TCO ( Tail-Call Optimized ) as its return is the last call to itself.
另请注意,此递归函数是TCO( Tail-Call Optimized ),因为它的返回是对自身的最后一次调用。
Additionally, you may want targeted properties . 此外,您可能需要目标属性 。 In this case, you may want to condense objects based upon
id
, quantity
, or another property. 在这种情况下,您可能希望根据
id
, quantity
或其他属性压缩对象。 This approach could have a small book written about it and requires object-juxtaposition and can get very complex. 这种方法可能有一本关于它的小书,需要对象并置,并且可能变得非常复杂。 I've written a small library for this which is available upon request.
我已经为此编写了一个小型库,可根据要求提供。
Hope this helps! 希望这可以帮助!
do you want to overwrite a property if the names are the same but the values are not? 如果名称相同但值不是,是否要覆盖属性?
And do you want to permanently change one of the original objects, 你想永久改变一个原始对象,
or do you want a new merged object returned? 或者你想要一个新的合并对象返回?
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];
}
}
}
}
jquery has a boolean for deep copy. jquery有一个深度复制的布尔值。 You could do something like that:
你可以这样做:
MergeRecursive = function(arr1, arr2){
$.extend(true, arr1, arr2);
return arr1;
};
Also you can edit this function to support n-arrays to merge. 您也可以编辑此函数以支持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;
};
So now you can do 所以现在你可以做到
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);
Yahoo UI (YUI) also has a helper function for this: Yahoo UI(YUI)也有一个辅助函数:
http://developer.yahoo.com/yui/examples/yahoo/yahoo_merge.html http://developer.yahoo.com/yui/examples/yahoo/yahoo_merge.html
YAHOO.namespace('example');
YAHOO.example.set1 = { foo : "foo" };
YAHOO.example.set2 = { foo : "BAR", bar : "bar" };
YAHOO.example.set3 = { foo : "FOO", baz : "BAZ" };
var Ye = YAHOO.example;
var merged = YAHOO.lang.merge(Ye.set1, Ye.set2, Ye.set3);
In 2019 you have 2 good options: 在2019年,您有两个不错的选择:
Object assigning [ doc ] 对象分配 [ doc ]
const result = Object.assign({}, baseObject, updatingObject);
Object spreading [ doc ] 对象传播 [ doc ]
const result = { ...baseObject, ...updatingObject};
The first one tends to be safer, more standard and polyvalent. 第一种趋向于更安全,更标准和多价。 A good pros and cons here
这里有利有弊
I needed a deep-object-merging. 我需要一个深层对象合并。 So all of the other answers didn't help me very much.
所以其他所有答案对我都没有帮助。 _.extend and jQuery.extend do well, unless you have a recursive array like i do.
_.extend和jQuery.extend做得很好,除非你像我一样有一个递归数组。 But it ain't so bad, you can program it in five minutes:
但它不是那么糟糕,你可以在五分钟内编程:
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;
}
To merge arrays in jQuery what about $.merge? 要在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';
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;
};
Tests 测试
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 }
Here is the best solution. 这是最好的解决方案。
obj1.unshift.apply( obj1, obj2 );
Also, obj1
can grow inside a loop without any problem. 此外,
obj1
可以在循环内生长而没有任何问题。 (lets say obj2
is dynamic) (假设
obj2
是动态的)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.