我需要能够在运行时合并两个(非常简单)JavaScript对象。例如,我想:
var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }
obj1.merge(obj2);
//obj1 now has three properties: food, car, and animal
是否有一种内置的方法来实现这一点?我不需要递归,也不需要合并函数,只需要平面对象上的方法。
我需要能够在运行时合并两个(非常简单)JavaScript对象。例如,我想:
var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }
obj1.merge(obj2);
//obj1 now has three properties: food, car, and animal
是否有一种内置的方法来实现这一点?我不需要递归,也不需要合并函数,只需要平面对象上的方法。
当前回答
我今天需要合并对象,这个问题(和答案)对我帮助很大。我尝试了一些答案,但没有一个符合我的需要,所以我组合了一些答案并自己添加了一些东西,并提出了一个新的合并函数。这里是:
var merge = function() {
var obj = {},
i = 0,
il = arguments.length,
key;
for (; i < il; i++) {
for (key in arguments[i]) {
if (arguments[i].hasOwnProperty(key)) {
obj[key] = arguments[i][key];
}
}
}
return obj;
};
一些示例用法:
var t1 = {
key1: 1,
key2: "test",
key3: [5, 2, 76, 21]
};
var t2 = {
key1: {
ik1: "hello",
ik2: "world",
ik3: 3
}
};
var t3 = {
key2: 3,
key3: {
t1: 1,
t2: 2,
t3: {
a1: 1,
a2: 3,
a4: [21, 3, 42, "asd"]
}
}
};
console.log(merge(t1, t2));
console.log(merge(t1, t3));
console.log(merge(t2, t3));
console.log(merge(t1, t2, t3));
console.log(merge({}, t1, { key1: 1 }));
其他回答
var firstObject = {
key1 : 'value1',
key2 : 'value2'
};
var secondObject={
...firstObject,
key3 : 'value3',
key4 : 'value4',
key5 : 'value5'
}
console.log(firstObject);
console.log(secondObject);
我在谷歌上搜索了合并对象财产的代码,结果出现在这里。然而,由于没有递归合并的代码,我自己编写了它。(也许jQuery扩展是递归的BTW?)无论如何,希望其他人也会发现它很有用。
(现在代码不使用Object.prototype:)
Code
/*
* Recursively merge properties of two objects
*/
function MergeRecursive(obj1, obj2) {
for (var p in obj2) {
try {
// Property in destination object set; update its value.
if ( obj2[p].constructor==Object ) {
obj1[p] = MergeRecursive(obj1[p], obj2[p]);
} else {
obj1[p] = obj2[p];
}
} catch(e) {
// Property in destination object not set; create it and set its value.
obj1[p] = obj2[p];
}
}
return obj1;
}
一个例子
o1 = { a : 1,
b : 2,
c : {
ca : 1,
cb : 2,
cc : {
cca : 100,
ccb : 200 } } };
o2 = { a : 10,
c : {
ca : 10,
cb : 20,
cc : {
cca : 101,
ccb : 202 } } };
o3 = MergeRecursive(o1, o2);
生成类似o3的对象
o3 = { a : 10,
b : 2,
c : {
ca : 10,
cb : 20,
cc : {
cca : 101,
ccb : 202 } } };
Use:
//Takes any number of objects and returns one merged object
var objectMerge = function(){
var out = {};
if(!arguments.length)
return out;
for(var i=0; i<arguments.length; i++) {
for(var key in arguments[i]){
out[key] = arguments[i][key];
}
}
return out;
}
测试方法:
console.log(objectMerge({a:1, b:2}, {a:2, c:4}));
结果是:
{ a: 2, b: 2, c: 4 }
ECMAScript 2018标准方法
您可以使用对象扩散:
let merged = {...obj1, ...obj2};
merged现在是obj1和obj2的并集。obj2中的财产将覆盖obj1中的属性。
/** There's no limit to the number of objects you can merge.
* Later properties overwrite earlier properties with the same name. */
const allRules = {...obj1, ...obj2, ...obj3};
这里还有此语法的MDN文档。如果您正在使用babel,则需要@babel/plugin提议对象rest spread插件才能工作(该插件包含在ES2018中的@babel/preset-env中)。
ECMAScript 2015(ES6)标准方法
/* For the case in question, you would do: */
Object.assign(obj1, obj2);
/** There's no limit to the number of objects you can merge.
* All objects get merged into the first object.
* Only the object in the first argument is mutated and returned.
* Later properties overwrite earlier properties with the same name. */
const allRules = Object.assign({}, obj1, obj2, obj3, etc);
(参见MDN JavaScript参考)
ES5及更早版本的方法
for (var attrname in obj2) { obj1[attrname] = obj2[attrname]; }
请注意,这将简单地将obj2的所有属性添加到obj1中,如果您仍然希望使用未修改的obj1,那么这可能不是您想要的。
如果你使用的是一个在你的原型上到处都是垃圾的框架,那么你必须通过hasOwnProperty这样的检查来获得更高的效率,但这段代码在99%的情况下都是有效的。
示例函数:
/**
* Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
* @param obj1
* @param obj2
* @returns obj3 a new object based on obj1 and obj2
*/
function merge_options(obj1,obj2){
var obj3 = {};
for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
return obj3;
}
最好的方法是使用Object.defineProperty添加一个不可枚举的适当属性。
通过这种方式,您仍然可以迭代对象财产,而无需使用Object.prototype.extend创建属性时新创建的“extend”。
希望这有助于:
Object.defineProperty(Object.prototype, "extend", { enumerable: false, value: function(from) { var props = Object.getOwnPropertyNames(from); var dest = this; props.forEach(function(name) { if (name in dest) { var destination = Object.getOwnPropertyDescriptor(from, name); Object.defineProperty(dest, name, destination); } }); return this; } });
一旦你做到了这一点,你就可以做到:
var obj = { name: 'stack', finish: 'overflow' } var replacement = { name: 'stock' }; obj.extend(replacement);
我刚刚在这里写了一篇博文:http://onemoredigit.com/post/1527191998/extending-objects-in-node-js