我需要能够在运行时合并两个(非常简单的)JavaScript对象。例如,我想:
var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }
obj1.merge(obj2);
//obj1 now has three properties: food, car, and animal
有没有人有这样的脚本或知道内置的方法来做到这一点?我不需要递归,我不需要合并函数,只需要平面对象上的方法。
答案 0 :(得分:2446)
ECMAScript 2018标准方法
您可以使用object spread:
let merged = {...obj1, ...obj2};
/** 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};
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);
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;
}
答案 1 :(得分:1161)
jQuery还有一个实用工具:http://api.jquery.com/jQuery.extend/。
取自jQuery文档:
// Merge options object into settings object
var settings = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };
jQuery.extend(settings, options);
// Now the content of settings object is the following:
// { validate: true, limit: 5, name: "bar" }
以上代码会改变名为 settings
的现有对象。
如果您想在不修改任何参数的情况下创建新对象,请使用以下命令:
var defaults = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };
/* Merge defaults and options, without modifying defaults */
var settings = $.extend({}, defaults, options);
// The content of settings variable is now the following:
// {validate: true, limit: 5, name: "bar"}
// The 'defaults' and 'options' variables remained the same.
答案 2 :(得分:327)
Harmony ECMAScript 2015 (ES6)指定Object.assign
即可执行此操作。
Object.assign(obj1, obj2);
目前的浏览器支持为getting better,但如果您正在为没有支持的浏览器进行开发,则可以使用polyfill。
答案 3 :(得分:251)
我用google搜索代码来合并对象属性,最后来到这里。但是由于没有任何递归合并代码,我自己写了。 (也许jQuery扩展是递归BTW?)无论如何,希望其他人也会觉得它很有用。
(现在代码不使用Object.prototype
:)
/*
* 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 } } };
答案 4 :(得分:173)
请注意,underscore.js
的extend
-method在单行中执行此操作:
_.extend({name : 'moe'}, {age : 50});
=> {name : 'moe', age : 50}
答案 5 :(得分:85)
与jQuery extend()类似,您在AngularJS中具有相同的功能:
// Merge the 'options' object into the 'settings' object
var settings = {validate: false, limit: 5, name: "foo"};
var options = {validate: true, name: "bar"};
angular.extend(settings, options);
答案 6 :(得分:64)
我今天需要合并对象,这个问题(和答案)对我帮助很大。我尝试了一些答案,但没有一个符合我的需求,所以我结合了一些答案,自己添加了一些东西,并提出了一个新的合并功能。这是:
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 }));
答案 7 :(得分:47)
您可以使用object spread properties - 目前是第3阶段ECMAScript提案。
const obj1 = { food: 'pizza', car: 'ford' };
const obj2 = { animal: 'dog' };
const obj3 = { ...obj1, ...obj2 };
console.log(obj3);
&#13;
答案 8 :(得分:40)
在分配之前,应修改给定的解决方案以检查source.hasOwnProperty(property)
循环中的for..in
- 否则,您最终会复制整个原型链的属性,这很少需要...
答案 9 :(得分:38)
Object.assign
方法是ECMAScript 2015(ES6)标准的一部分,可以完全满足您的需求。 (IE
不支持)
var clone = Object.assign({}, obj);
Object.assign()方法用于将所有可枚举的自有属性的值从一个或多个源对象复制到目标对象。
支持旧浏览器的 polyfill :
if (!Object.assign) {
Object.defineProperty(Object, 'assign', {
enumerable: false,
configurable: true,
writable: true,
value: function(target) {
'use strict';
if (target === undefined || target === null) {
throw new TypeError('Cannot convert first argument to object');
}
var to = Object(target);
for (var i = 1; i < arguments.length; i++) {
var nextSource = arguments[i];
if (nextSource === undefined || nextSource === null) {
continue;
}
nextSource = Object(nextSource);
var keysArray = Object.keys(nextSource);
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
var nextKey = keysArray[nextIndex];
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
if (desc !== undefined && desc.enumerable) {
to[nextKey] = nextSource[nextKey];
}
}
}
return to;
}
});
}
答案 10 :(得分:33)
以下两个可能是一个很好的起点。 lodash还有针对这些特殊需求的定制功能!
_.extend
(http://underscorejs.org/#extend)
_.merge
(https://lodash.com/docs#merge)
答案 11 :(得分:26)
顺便说一下,你们所做的就是覆盖属性,而不是合并......
这是JavaScript对象区域真正合并的方式:只有to
对象中不是对象本身的键才会被from
覆盖。其他所有内容都将 真正合并 。当然,您可以将此行为更改为不覆盖仅存在to[n] is undefined
等的任何内容......:
var realMerge = function (to, from) {
for (n in from) {
if (typeof to[n] != 'object') {
to[n] = from[n];
} else if (typeof from[n] == 'object') {
to[n] = realMerge(to[n], from[n]);
}
}
return to;
};
用法:
var merged = realMerge(obj1, obj2);
答案 12 :(得分:24)
这是我的刺痛
简短:)
/*
Recursively merge properties and return new object
obj1 <- obj2 [ <- ... ]
*/
function merge () {
var dst = {}
,src
,p
,args = [].splice.call(arguments, 0)
;
while (args.length > 0) {
src = args.splice(0, 1)[0];
if (toString.call(src) == '[object Object]') {
for (p in src) {
if (src.hasOwnProperty(p)) {
if (toString.call(src[p]) == '[object Object]') {
dst[p] = merge(dst[p] || {}, src[p]);
} else {
dst[p] = src[p];
}
}
}
}
}
return dst;
}
示例:
a = {
"p1": "p1a",
"p2": [
"a",
"b",
"c"
],
"p3": true,
"p5": null,
"p6": {
"p61": "p61a",
"p62": "p62a",
"p63": [
"aa",
"bb",
"cc"
],
"p64": {
"p641": "p641a"
}
}
};
b = {
"p1": "p1b",
"p2": [
"d",
"e",
"f"
],
"p3": false,
"p4": true,
"p6": {
"p61": "p61b",
"p64": {
"p642": "p642b"
}
}
};
c = {
"p1": "p1c",
"p3": null,
"p6": {
"p62": "p62c",
"p64": {
"p643": "p641c"
}
}
};
d = merge(a, b, c);
/*
d = {
"p1": "p1c",
"p2": [
"d",
"e",
"f"
],
"p3": null,
"p5": null,
"p6": {
"p61": "p61b",
"p62": "p62c",
"p63": [
"aa",
"bb",
"cc"
],
"p64": {
"p641": "p641a",
"p642": "p642b",
"p643": "p641c"
}
},
"p4": true
};
*/
答案 13 :(得分:18)
<强> Object.assign()强>
ECMAScript 2015(ES6)
这是一项新技术,是ECMAScript 2015(ES6)标准的一部分。 该技术规范已经完成,但请查看兼容性表,了解各种浏览器的使用情况和实施状态。
Object.assign()方法用于将所有可枚举的自有属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };
var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, target object itself is changed.
答案 14 :(得分:18)
对于不太复杂的对象,您可以使用JSON:
var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog', car: 'chevy'}
var objMerge;
objMerge = JSON.stringify(obj1) + JSON.stringify(obj2);
// {"food": "pizza","car":"ford"}{"animal":"dog","car":"chevy"}
objMerge = objMerge.replace(/\}\{/, ","); // \_ replace with comma for valid JSON
objMerge = JSON.parse(objMerge); // { food: 'pizza', animal: 'dog', car: 'chevy'}
// Of same keys in both objects, the last object's value is retained_/
请注意,在此示例中,“} {” 不得在字符串中出现 !
答案 15 :(得分:16)
执行此操作的最佳方法是使用Object.defineProperty添加不可枚举的适当属性。
通过这种方式,您仍然可以迭代对象属性,而无需使用Object.prototype.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
答案 16 :(得分:15)
您只需使用jQuery extend
var obj1 = { val1: false, limit: 5, name: "foo" };
var obj2 = { val2: true, name: "bar" };
jQuery.extend(obj1, obj2);
现在obj1
包含obj1
和obj2
答案 17 :(得分:15)
答案 18 :(得分:12)
Prototype有这个:
Object.extend = function(destination,source) {
for (var property in source)
destination[property] = source[property];
return destination;
}
obj1.extend(obj2)
会做你想做的事。
答案 19 :(得分:11)
如果有人使用Google Closure Library:
goog.require('goog.object');
var a = {'a': 1, 'b': 2};
var b = {'b': 3, 'c': 4};
goog.object.extend(a, b);
// Now object a == {'a': 1, 'b': 3, 'c': 4};
Similar helper function exists for array:
var a = [1, 2];
var b = [3, 4];
goog.array.extend(a, b); // Extends array 'a'
goog.array.concat(a, b); // Returns concatenation of array 'a' and 'b'
答案 20 :(得分:9)
我扩展了David Coallier的方法:
如果override为false,则不会覆盖任何属性,但会添加新属性。
使用方法: obj.merge(merges ... [,override]);
这是我的代码:
Object.defineProperty(Object.prototype, "merge", {
enumerable: false,
value: function () {
var override = true,
dest = this,
len = arguments.length,
props, merge, i, from;
if (typeof(arguments[arguments.length - 1]) === "boolean") {
override = arguments[arguments.length - 1];
len = arguments.length - 1;
}
for (i = 0; i < len; i++) {
from = arguments[i];
if (from != null) {
Object.getOwnPropertyNames(from).forEach(function (name) {
var descriptor;
// nesting
if ((typeof(dest[name]) === "object" || typeof(dest[name]) === "undefined")
&& typeof(from[name]) === "object") {
// ensure proper types (Array rsp Object)
if (typeof(dest[name]) === "undefined") {
dest[name] = Array.isArray(from[name]) ? [] : {};
}
if (override) {
if (!Array.isArray(dest[name]) && Array.isArray(from[name])) {
dest[name] = [];
}
else if (Array.isArray(dest[name]) && !Array.isArray(from[name])) {
dest[name] = {};
}
}
dest[name].merge(from[name], override);
}
// flat properties
else if ((name in dest && override) || !(name in dest)) {
descriptor = Object.getOwnPropertyDescriptor(from, name);
if (descriptor.configurable) {
Object.defineProperty(dest, name, descriptor);
}
}
});
}
}
return this;
}
});
示例和测试用例:
function clone (obj) {
return JSON.parse(JSON.stringify(obj));
}
var obj = {
name : "trick",
value : "value"
};
var mergeObj = {
name : "truck",
value2 : "value2"
};
var mergeObj2 = {
name : "track",
value : "mergeObj2",
value2 : "value2-mergeObj2",
value3 : "value3"
};
assertTrue("Standard", clone(obj).merge(mergeObj).equals({
name : "truck",
value : "value",
value2 : "value2"
}));
assertTrue("Standard no Override", clone(obj).merge(mergeObj, false).equals({
name : "trick",
value : "value",
value2 : "value2"
}));
assertTrue("Multiple", clone(obj).merge(mergeObj, mergeObj2).equals({
name : "track",
value : "mergeObj2",
value2 : "value2-mergeObj2",
value3 : "value3"
}));
assertTrue("Multiple no Override", clone(obj).merge(mergeObj, mergeObj2, false).equals({
name : "trick",
value : "value",
value2 : "value2",
value3 : "value3"
}));
var deep = {
first : {
name : "trick",
val : "value"
},
second : {
foo : "bar"
}
};
var deepMerge = {
first : {
name : "track",
anotherVal : "wohoo"
},
second : {
foo : "baz",
bar : "bam"
},
v : "on first layer"
};
assertTrue("Deep merges", clone(deep).merge(deepMerge).equals({
first : {
name : "track",
val : "value",
anotherVal : "wohoo"
},
second : {
foo : "baz",
bar : "bam"
},
v : "on first layer"
}));
assertTrue("Deep merges no override", clone(deep).merge(deepMerge, false).equals({
first : {
name : "trick",
val : "value",
anotherVal : "wohoo"
},
second : {
foo : "bar",
bar : "bam"
},
v : "on first layer"
}));
var obj1 = {a: 1, b: "hello"};
obj1.merge({c: 3});
assertTrue(obj1.equals({a: 1, b: "hello", c: 3}));
obj1.merge({a: 2, b: "mom", d: "new property"}, false);
assertTrue(obj1.equals({a: 1, b: "hello", c: 3, d: "new property"}));
var obj2 = {};
obj2.merge({a: 1}, {b: 2}, {a: 3});
assertTrue(obj2.equals({a: 3, b: 2}));
var a = [];
var b = [1, [2, 3], 4];
a.merge(b);
assertEquals(1, a[0]);
assertEquals([2, 3], a[1]);
assertEquals(4, a[2]);
var o1 = {};
var o2 = {a: 1, b: {c: 2}};
var o3 = {d: 3};
o1.merge(o2, o3);
assertTrue(o1.equals({a: 1, b: {c: 2}, d: 3}));
o1.b.c = 99;
assertTrue(o2.equals({a: 1, b: {c: 2}}));
// checking types with arrays and objects
var bo;
a = [];
bo = [1, {0:2, 1:3}, 4];
b = [1, [2, 3], 4];
a.merge(b);
assertTrue("Array stays Array?", Array.isArray(a[1]));
a = [];
a.merge(bo);
assertTrue("Object stays Object?", !Array.isArray(a[1]));
a = [];
a.merge(b);
a.merge(bo);
assertTrue("Object overrides Array", !Array.isArray(a[1]));
a = [];
a.merge(b);
a.merge(bo, false);
assertTrue("Object does not override Array", Array.isArray(a[1]));
a = [];
a.merge(bo);
a.merge(b);
assertTrue("Array overrides Object", Array.isArray(a[1]));
a = [];
a.merge(bo);
a.merge(b, false);
assertTrue("Array does not override Object", !Array.isArray(a[1]));
我的equals方法可以在这里找到:Object comparison in JavaScript
答案 21 :(得分:9)
Object.merge(obj1, obj2);
答案 22 :(得分:9)
合并对象很简单。
var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog', car: 'BMW' }
var obj3 = {a: "A"}
var mergedObj = Object.assign(obj1,obj2,obj3)
console.log(mergedObj);
对象从右向左合并,这意味着将覆盖与其右侧对象具有相同属性的对象。
在此示例中,obj2.car
会覆盖obj1.car
答案 23 :(得分:8)
在Ext JS 4中,可以按如下方式完成:
var mergedObject = Ext.Object.merge(object1, object2)
// Or shorter:
var mergedObject2 = Ext.merge(object1, object2)
请参阅 merge( object ) : Object 。
答案 24 :(得分:7)
基于Markus'和vsync' answer,这是一个扩展版本。该函数接受任意数量的参数。它可用于在DOM节点上设置属性并生成值的深层副本。但是,第一个参数是通过引用给出的。
要检测DOM节点,使用isDOMNode()函数(请参阅堆栈溢出问题 JavaScript isDOM — How do you check if a JavaScript Object is a DOM Object? )
在Opera 11,Firefox 6,Internet Explorer 8和Google Chrome 16中进行了测试。
function mergeRecursive() {
// _mergeRecursive does the actual job with two arguments.
var _mergeRecursive = function (dst, src) {
if (isDOMNode(src) || typeof src !== 'object' || src === null) {
return dst;
}
for (var p in src) {
if (!src.hasOwnProperty(p))
continue;
if (src[p] === undefined)
continue;
if ( typeof src[p] !== 'object' || src[p] === null) {
dst[p] = src[p];
} else if (typeof dst[p]!=='object' || dst[p] === null) {
dst[p] = _mergeRecursive(src[p].constructor===Array ? [] : {}, src[p]);
} else {
_mergeRecursive(dst[p], src[p]);
}
}
return dst;
}
// Loop through arguments and merge them into the first argument.
var out = arguments[0];
if (typeof out !== 'object' || out === null)
return out;
for (var i = 1, il = arguments.length; i < il; i++) {
_mergeRecursive(out, arguments[i]);
}
return out;
}
设置HTML元素的innerHTML和样式
mergeRecursive(
document.getElementById('mydiv'),
{style: {border: '5px solid green', color: 'red'}},
{innerHTML: 'Hello world!'});
合并数组和对象。请注意,undefined可用于保留左侧数组/对象中的值。
o = mergeRecursive({a:'a'}, [1,2,3], [undefined, null, [30,31]], {a:undefined, b:'b'});
// o = {0:1, 1:null, 2:[30,31], a:'a', b:'b'}
任何不属于JavaScript对象(包括null)的参数都将被忽略。除第一个参数外,DOM节点也被丢弃。请注意,即像新String()一样创建的字符串实际上是对象。
o = mergeRecursive({a:'a'}, 1, true, null, undefined, [1,2,3], 'bc', new String('de'));
// o = {0:'d', 1:'e', 2:3, a:'a'}
如果要将两个对象合并为一个新对象(不影响两者中的任何一个),请将{}作为第一个参数
var a={}, b={b:'abc'}, c={c:'cde'}, o;
o = mergeRecursive(a, b, c);
// o===a is true, o===b is false, o===c is false
修改(由ReaperSoon提供):
还要合并数组
function mergeRecursive(obj1, obj2) {
if (Array.isArray(obj2)) { return obj1.concat(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 if (Array.isArray(obj2[p])) {
obj1[p] = obj1[p].concat(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;
}
答案 25 :(得分:6)
哇..这是我在多个页面上看过的第一篇StackOverflow帖子。抱歉添加另一个&#34;答案&#34;
此方法适用于 ES5&amp;早些时候 - 还有很多其他解决ES6问题的答案。
我没有看到任何使用arguments
属性的&#34; deep&#34; 对象合并。这是我的答案 - 紧凑&amp; 递归,允许传递无限制的对象参数:
function extend() {
for (var o = {}, i = 0; i < arguments.length; i++) {
// if (arguments[i].constructor !== Object) continue;
for (var k in arguments[i]) {
if (arguments[i].hasOwnProperty(k)) {
o[k] = arguments[i][k].constructor === Object ? extend(o[k] || {}, arguments[i][k]) : arguments[i][k];
}
}
}
return o;
}
注释掉的部分是可选的..它只会跳过不是对象传递的参数(防止错误)。
示例:强>
extend({
api: 1,
params: {
query: 'hello'
}
}, {
params: {
query: 'there'
}
});
// outputs {api: 1, params: {query: 'there'}}
这个答案现在只是海洋中的一滴......
答案 26 :(得分:5)
你应该使用lodash&#39; defaultsDeep
_.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } });
// → { 'user': { 'name': 'barney', 'age': 36 } }
答案 27 :(得分:5)
使用Underscore.js,合并一个对象数组:
var arrayOfObjects = [ {a:1}, {b:2, c:3}, {d:4} ];
_(arrayOfObjects).reduce(function(memo, o) { return _(memo).extend(o); });
结果是:
Object {a: 1, b: 2, c: 3, d: 4}
答案 28 :(得分:5)
var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }
// result
result: {food: "pizza", car: "ford", animal: "dog"}
使用jQuery.extend()-Link
// Merge obj1 & obj2 to result
var result1 = $.extend( {}, obj1, obj2 );
使用_.merge()-Link
// Merge obj1 & obj2 to result
var result2 = _.merge( {}, obj1, obj2 );
使用_.extend()-Link
// Merge obj1 & obj2 to result
var result3 = _.extend( {}, obj1, obj2 );
使用Object.assign()ECMAScript 2015(ES6)-Link
// Merge obj1 & obj2 to result
var result4 = Object.assign( {}, obj1, obj2 );
全部输出
obj1: { animal: 'dog' }
obj2: { food: 'pizza', car: 'ford' }
result1: {food: "pizza", car: "ford", animal: "dog"}
result2: {food: "pizza", car: "ford", animal: "dog"}
result3: {food: "pizza", car: "ford", animal: "dog"}
result4: {food: "pizza", car: "ford", animal: "dog"}
答案 29 :(得分:4)
使用遵循ES6版本的Spread运算符
var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }
let result = {...obj1,...obj2};
console.log(result)
output { food: 'pizza', car: 'ford', animal: 'dog' }
答案 30 :(得分:4)
值得一提的是140byt.es collection的版本是在最小的空间内完成任务,值得一试:
代码:
function m(a,b,c){for(c in b)b.hasOwnProperty(c)&&((typeof a[c])[0]=='o'?m(a[c],b[c]):a[c]=b[c])}
用于您的目的:
m(obj1,obj2);
答案 31 :(得分:3)
我使用纯JavaScript中的以下内容。它从最右边的参数开始,并将它们一直组合到第一个参数。没有返回值,只修改了第一个参数,最左边的参数(第一个参数除外)在属性上具有最高权重。
var merge = function() {
var il = arguments.length;
for (var i = il - 1; i > 0; --i) {
for (var key in arguments[i]) {
if (arguments[i].hasOwnProperty(key)) {
arguments[0][key] = arguments[i][key];
}
}
}
};
答案 32 :(得分:2)
我的方式:
function mergeObjects(defaults, settings) {
Object.keys(defaults).forEach(function(key_default) {
if (typeof settings[key_default] == "undefined") {
settings[key_default] = defaults[key_default];
} else if (isObject(defaults[key_default]) && isObject(settings[key_default])) {
mergeObjects(defaults[key_default], settings[key_default]);
}
});
function isObject(object) {
return Object.prototype.toString.call(object) === '[object Object]';
}
return settings;
}
:)
答案 33 :(得分:2)
使用:
//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 }
答案 34 :(得分:2)
检查以下两行:
from = arguments[i];
Object.getOwnPropertyNames(from).forEach(function (name) {
需要针对null对象检查“from”...例如,如果合并来自先前在服务器上创建的Ajax响应的对象,则对象属性的值可以为“null” ,在这种情况下,上面的代码会产生错误说:
“from”不是有效对象
因此,例如,使用“if(from!= null){...}”包装“... Object.getOwnPropertyNames(from).forEach ...”函数将防止发生该错误。
答案 35 :(得分:2)
function extend(o, o1, o2){
if( !(o instanceof Object) ) o = {};
copy(o, o1);
if( o2 )
copy(o, o2)
function isObject(obj) {
var type = Object.prototype.toString.call(obj);
return obj === Object(obj) && type != '[object Array]' && type != '[object Function]';
};
function copy(a,b){
// copy o2 to o
for( var key in b )
if( b.hasOwnProperty(key) ){
if( isObject(b[key]) ){
if( !isObject(a[key]) )
a[key] = Object.assign({}, b[key]);
else copy(a[key], b[key])
}
else
a[key] = b[key];
}
}
return o;
};
var o1 = {a:{foo:1}, b:1},
o2 = {a:{bar:2}, b:[1], c:()=>{}},
newMerged = extend({}, o1, o2);
console.log( newMerged )
console.log( o1 )
console.log( o2 )
答案 36 :(得分:2)
ES2018 / TypeScript:许多答案都可以,但是当您需要合并两个对象而不会覆盖重叠的对象键时,我想出了一个更为优雅的解决方案。
我的函数还接受无限数量的对象作为函数参数合并:
(我在这里使用TypeScript表示法,如果您使用的是纯JavaScript,请随时删除函数参数中的:object[]
类型。)
const merge = (...objects: object[]) => {
return objects.reduce((prev, next) => {
Object.keys(prev).forEach(key => {
next[key] = { ...next[key], ...prev[key] }
})
return next
})
}
答案 37 :(得分:1)
我开始使用JavaScript了,如果我错了,请纠正我。
但是如果你可以合并任意数量的对象会不会更好?这是我使用原生Arguments
对象的方式。
关键是你可以将任意数量的参数传递给JavaScript函数,而无需在函数声明中定义它们。如果不使用Arguments对象,则无法访问它们。
function mergeObjects() (
var tmpObj = {};
for(var o in arguments) {
for(var m in arguments[o]) {
tmpObj[m] = arguments[o][m];
}
}
return tmpObj;
}
答案 38 :(得分:1)
let obj1 = {a:1, b:2};
let obj2 = {c:3, d:4};
let merged = {...obj1, ...obj2};
console.log(merged);
答案 39 :(得分:1)
这是我在代码库中用来合并的内容。
function merge(to, from) {
if (typeof to === 'object' && typeof from === 'object') {
for (var pro in from) {
if (from.hasOwnProperty(pro)) {
to[pro] = from[pro];
}
}
}
else{
throw "Merge function can apply only on object";
}
}
答案 40 :(得分:1)
使用 Object.assign 和 spread运算符合并两个对象。
方法错误(由于定位为o1,因此修改了原始对象)
var o1 = { X: 10 };
var o2 = { Y: 20 };
var o3 = { Z: 30 };
var merge = Object.assign(o1, o2, o3);
console.log(merge) // {X:10, Y:20, Z:30}
console.log(o1) // {X:10, Y:20, Z:30}
正确的方法
Object.assign({},o1,o2,o3) ==> 定位新对象
{... o1,... o2,... o3} ==> 传播对象
var o1 = { X: 10 };
var o2 = { Y: 20 };
var o3 = { Z: 30 };
console.log('Does not modify original objects because target {}');
var merge = Object.assign({}, o1, o2, o3);
console.log(merge); // { X: 10, Y: 20, Z: 30 }
console.log(o1)
console.log('Does not modify original objects')
var spreadMerge = {...o1, ...o2, ...o3};
console.log(spreadMerge);
console.log(o1);
答案 41 :(得分:1)
ES5兼容原生单行:
var merged = [obj1, obj2].reduce(function(a, o) { for(k in o) a[k] = o[k]; return a; }, {})
答案 42 :(得分:1)
Prototype中的正确实现应如下所示:
var obj1 = {food: 'pizza', car: 'ford'}
var obj2 = {animal: 'dog'}
obj1 = Object.extend(obj1, obj2);
答案 43 :(得分:1)
您可以按照我的方法
合并对象
var obj1 = { food: 'pizza', car: 'ford' };
var obj2 = { animal: 'dog' };
var result = mergeObjects([obj1, obj2]);
console.log(result);
document.write("result: <pre>" + JSON.stringify(result, 0, 3) + "</pre>");
function mergeObjects(objectArray) {
if (objectArray.length) {
var b = "", i = -1;
while (objectArray[++i]) {
var str = JSON.stringify(objectArray[i]);
b += str.slice(1, str.length - 1);
if (objectArray[i + 1]) b += ",";
}
return JSON.parse("{" + b + "}");
}
return {};
}
答案 44 :(得分:1)
似乎这应该是您所需要的:
df = pd.DataFrame(dict(
A=['icon1', 'icon1', 'icon2', 'icon2'],
B=[{'ap1': {'item': 1}, 'ap2': {'item': 2}}, {'ap3': {'item': 3}}] * 2
))
此后,obj1现在应具有以下值:
var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }
var obj1 = { ...obj1, ...obj2 }
答案 45 :(得分:1)
浅
var obj = { name : "Jacob" , address : ["America"] }
var obj2 = { name : "Shaun" , address : ["Honk Kong"] }
var merged = Object.assign({} , obj,obj2 ); //shallow merge
obj2.address[0] = "new city"
result.address [0]更改为“新城市”,即合并对象也更改了。这是浅合并的问题。
深
var obj = { name : "Jacob" , address : ["America"] }
var obj2 = { name : "Shaun" , address : ["Honk Kong"] }
var result = Object.assign({} , JSON.parse(JSON.stringify(obj)),JSON.parse(JSON.stringify(obj2)) )
obj2.address[0] = "new city"
result.address [0]不变
答案 46 :(得分:1)
答案 47 :(得分:1)
对于使用Node.js的用户,有一个NPM模块:node.extend
npm install node.extend
var extend = require('node.extend');
var destObject = extend(true, {}, sourceObject);
// Where sourceObject is the object whose properties will be copied into another.
答案 48 :(得分:0)
有多种方法可以实现这一目标:
Object.assign(targetObj, sourceObj);
targetObj = {...targetObj, ...sourceObj};
答案 49 :(得分:0)
您可以使用Object.assign方法。 例如:obj1 = Object.assign(obj1,obj2);
它创建json对象的深层副本。
答案 50 :(得分:0)
使用以下帮助器,您可以将两个对象合并为一个新对象:
function extend(obj, src) {
for (var key in src) {
if (src.hasOwnProperty(key)) obj[key] = src[key];
}
return obj;
}
// example
var a = { foo: true }, b = { bar: false };
var c = extend(a, b);
console.log(c);
// { foo: true, bar: false }
在将选项dict与功能或插件中的默认设置合并时,这通常很有用。
如果不需要支持IE 8,则可以使用Object.keys
来实现相同的功能:
function extend(obj, src) {
Object.keys(src).forEach(function(key) { obj[key] = src[key]; });
return obj;
}
这涉及较少的代码,并且速度更快。
答案 51 :(得分:0)
您可以通过三种方式做到这一点:-
方法一:-
// using spread ...
let obj1 = {
...obj2
};
方法 2:-
// using Object.assign() method
let obj1 = Object.assign({}, obj2);
方法 3:-
// using JSON
let obj1 = JSON.parse(JSON.stringify(obj2));
答案 52 :(得分:0)
我们可以创建一个空对象,并按for-loop
:
var obj1 = {
id: '1',
name: 'name'
}
var obj2 = {
c: 'c',
d: 'd'
}
var obj3 = {}
for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
console.log( obj1, obj2, obj3)
&#13;
答案 53 :(得分:0)
Object.assign(TargetObject, Obj1, Obj2, ...);
答案 54 :(得分:0)
使用 jQuery 库尝试这种方式
let obj1 = { food: 'pizza', car: 'ford' }
let obj2 = { animal: 'dog' }
console.log(jQuery.extend(obj1, obj2))
答案 55 :(得分:0)
我鼓励使用和使用不破坏原始来源的非破坏性方法,'Object.assign'是一种破坏性方法,它也恰好不是那么生产友好因为它停止在早期版本的浏览器上工作,而你无法用干净的方式修补它,或者替代它。
无论解决方案如何,合并JS对象总是无法实现或不完整。但是,合并符合JSON的兼容对象只需一步就能够编写一个简单易用的代码片段,将一系列JS对象合并到一个包含所有唯一属性名称及其相应值的非主动方法中。用于预期目的的单个主对象。
请记住,MSIE8是第一个为JSON对象添加本机支持的浏览器,这是一个很大的缓解,并且重用现有技术,总是一个受欢迎的机会。
将代码限制为JSON complant标准对象,比限制更具优势 - 因为这些对象也可以通过Internet传输。当然对于那些希望更深入向后兼容的人来说,总是有一个json插件。可以很容易地将其方法分配给外部代码中的JSON变量,而无需修改或重写正在使用的方法。
function Merge( ){
var a = [].slice.call( arguments ), i = 0;
while( a[i] )a[i] = JSON.stringify( a[i++] ).slice( 1,-1 );
return JSON.parse( "{"+ a.join() +"}" );
}
(当然有人可以给它一个更有意义的名字,我还没有决定;应该把它命名为JSONmerge)
用例:
var master = Merge( obj1, obj2, obj3, ...objn );
现在,与Object.assign
相反,这会使所有对象保持原状并处于原始状态(如果您做错了什么并且需要重新排序合并对象或者能够单独使用它们进行其他操作在再次合并之前)。
Merge参数的数量也仅限于 参数长度限制[这是巨大的]。
本机支持的JSON解析/字符串化已经是机器优化的,这意味着:它应该比任何脚本形式的JS循环更快。
对给定参数的迭代是使用while
完成的 - 被证明是JS中最快的循环。
简单地提及我们已经知道独特对象标签(键)的重复属性将被包含相同键标签的后一对象覆盖,这意味着您可以控制哪个属性是无害的。通过简单地排序或重新排序参数列表来接管前一个。获得一个干净和更新的主对象的好处,没有最终输出的dupes。
;
var obj1 = {a:1}, obj2 = {b:2}, obj3 = {c:3}
;
function Merge( ){
var a = [].slice.call( arguments ), i = 0;
while( a[i] )a[i] = JSON.stringify( a[i++] ).slice( 1,-1 );
return JSON.parse( "{"+ a.join() +"}" );
}
;
var master = Merge( obj1, obj2, obj3 )
;
console.log( JSON.stringify( master ) )
;
答案 56 :(得分:0)
实现此目标的可能方法如下:
if (!Object.prototype.merge){
Object.prototype.merge = function(obj){
var self = this;
Object.keys(obj).forEach(function(key){
self[key] = obj[key]
});
}
};
我不知道它是否比其他答案更好。在此方法中,您将merge function
添加到Objects
原型。这样您就可以致电obj1.merge(obj2);
注意:您应该验证您的参数以查看它是否为对象并“抛出”正确的Error
。如果不是Object.keys
将'抛出''错误'
答案 57 :(得分:0)
如果您使用的是Dojo Toolkit,那么合并两个对象的最佳方法是使用mixin。
以下是Dojo Toolkit mixin的示例:
// Dojo 1.7+ (AMD)
require(["dojo/_base/lang"], function(lang){
var a = { b:"c", d:"e" };
lang.mixin(a, { d:"f", g:"h" });
console.log(a); // b:c, d:f, g:h
});
// Dojo < 1.7
var a = { b:"c", d:"e" };
dojo.mixin(a, { d:"f", g:"h" });
console.log(a); // b:c, d:f, g:h
有关详情,请 mixin 。
答案 58 :(得分:0)
另一种方法:
function concat_collection(obj1, obj2) {
var i;
var arr = new Array();
var len1 = obj1.length;
for (i=0; i<len1; i++) {
arr.push(obj1[i]);
}
var len2 = obj2.length;
for (i=0; i<len2; i++) {
arr.push(obj2[i]);
}
return arr;
}
var ELEMENTS = concat_collection(A,B);
for(var i = 0; i < ELEMENTS.length; i++) {
alert(ELEMENTS[i].value);
}
答案 59 :(得分:0)
此解决方案可创建新对象,并能够处理多个对象。
此外,递归您可以选择想要的天气来覆盖值和对象。< / p>
function extendObjects() {
var newObject = {};
var overwriteValues = false;
var overwriteObjects = false;
for ( var indexArgument = 0; indexArgument < arguments.length; indexArgument++ ) {
if ( typeof arguments[indexArgument] !== 'object' ) {
if ( arguments[indexArgument] == 'overwriteValues_True' ) {
overwriteValues = true;
} else if ( arguments[indexArgument] == 'overwriteValues_False' ) {
overwriteValues = false;
} else if ( arguments[indexArgument] == 'overwriteObjects_True' ) {
overwriteObjects = true;
} else if ( arguments[indexArgument] == 'overwriteObjects_False' ) {
overwriteObjects = false;
}
} else {
extendObject( arguments[indexArgument], newObject, overwriteValues, overwriteObjects );
}
}
function extendObject( object, extendedObject, overwriteValues, overwriteObjects ) {
for ( var indexObject in object ) {
if ( typeof object[indexObject] === 'object' ) {
if ( typeof extendedObject[indexObject] === "undefined" || overwriteObjects ) {
extendedObject[indexObject] = object[indexObject];
}
extendObject( object[indexObject], extendedObject[indexObject], overwriteValues, overwriteObjects );
} else {
if ( typeof extendedObject[indexObject] === "undefined" || overwriteValues ) {
extendedObject[indexObject] = object[indexObject];
}
}
}
return extendedObject;
}
return newObject;
}
var object1 = { a : 1, b : 2, testArr : [888, { innArr : 1 }, 777 ], data : { e : 12, c : { lol : 1 }, rofl : { O : 3 } } };
var object2 = { a : 6, b : 9, data : { a : 17, b : 18, e : 13, rofl : { O : 99, copter : { mao : 1 } } }, hexa : { tetra : 66 } };
var object3 = { f : 13, g : 666, a : 333, data : { c : { xD : 45 } }, testArr : [888, { innArr : 3 }, 555 ] };
var newExtendedObject = extendObjects( 'overwriteValues_False', 'overwriteObjects_False', object1, object2, object3 );
newExtendedObject的内容:
{"a":1,"b":2,"testArr":[888,{"innArr":1},777],"data":{"e":12,"c":{"lol":1,"xD":45},"rofl":{"O":3,"copter":{"mao":1}},"a":17,"b":18},"hexa":{"tetra":66},"f":13,"g":666}
答案 60 :(得分:0)
我使用了Object.create()来保持默认设置(使用__proto__或Object.getPrototypeOf())。
function myPlugin( settings ){
var defaults = {
"keyName": [ "string 1", "string 2" ]
}
var options = Object.create( defaults );
for (var key in settings) { options[key] = settings[key]; }
}
myPlugin( { "keyName": ["string 3", "string 4" ] } );
这样我以后总能'concat()'或'push()'。
var newArray = options['keyName'].concat( options.__proto__['keyName'] );
注意:您需要在连接之前执行hasOwnProperty检查以避免重复。
答案 61 :(得分:0)
您可以为每个对象分配默认合并(可能是“继承”更好的名称)方法:
它应该与对象或实例化函数一起使用。
如果需要,下面的代码会处理覆盖合并的值:
Object.prototype.merge = function(obj, override) {
// Don't override by default
for (var key in obj) {
var n = obj[key];
var t = this[key];
this[key] = (override && t) ? n : t;
};
};
测试数据如下:
var Mammal = function () {
this.eyes = 2;
this.thinking_brain = false;
this.say = function () {
console.log('screaming like a mammal')};
}
var Human = function () {
this.thinking_brain = true;
this.say = function() {console.log('shouting like a human')};
}
john = new Human();
// Extend mammal, but do not override from mammal
john.merge(new Mammal());
john.say();
// Extend mammal and override from mammal
john.merge(new Mammal(), true);
john.say();
答案 62 :(得分:0)
A={a:1,b:function(){alert(9)}}
B={a:2,c:3}
A.merge = function(){for(var i in B){A[i]=B[i]}}
A.merge()
结果是:{a:2,c:3,b:function()}
答案 63 :(得分:0)
这会将obj
合并为“默认”def
。 obj
优先于两者中存在的任何内容,因为obj
已复制到def
。另请注意,这是递归的。
function mergeObjs(def, obj) {
if (typeof obj == 'undefined') {
return def;
} else if (typeof def == 'undefined') {
return obj;
}
for (var i in obj) {
if (obj[i] != null && obj[i].constructor == Object) {
def[i] = mergeObjs(def[i], obj[i]);
} else {
def[i] = obj[i];
}
}
return def;
}
a = {x : {y : [123]}}
b = {x : {z : 123}}
console.log(mergeObjs(a, b));
// {x: {y : [123], z : 123}}
答案 64 :(得分:-1)
<pre>
/**
This script can merge two multi dimensional associative array/objects in javascript by comparing given object with its reference and
will remove additional given keys, adding missed parameteres and also validating values without overhead. Also it will return the default values if no input presented with re-usable reference!
Tested on IE8 and greater.
**/
var module = (function(){
//To make our reference variable onchangable, have to put it into a function which is fster and more efficient than "JSON.parse(JSON.stringify(VARIABLE))"
var _defs = function(){
return {
//string, number and boolean are actually regex based validation keys on input values.
a: ["string", 'Defaul value for "a"'],
b: ["number", 300],
c: ["boolean", true],
d: {
da: ["boolean", true],
db: ["string", 'Defaul value for "db"'],
dc: {
dca: ["number", 200],
dcb: ["string", 'Default value for "dcb"'],
dcc: ["number", 500],
dcd: ["boolean", true]
},
dce: ["string", 'Default value for "dce"'],
},
e: ["number", 200],
f: ["boolean", 0],
g: ["", 'This is an internal extra parameter']
}
}
var _validation = {
number: function (defaultValue, userValue) {
if(/^[0-9]+$/.test(userValue)) //Only numbers allowed
return userValue;
else return defaultValue;
},
string: function (defaultValue, userValue) {
if(/^[a-zA-Z\s]*$/.test(userValue)) //Only A to Z case insentitive with space aloowed.
return userValue;
else return defaultValue;
},
boolean: function (defaultValue, userValue) {
if(typeof userValue === 'boolean') //True or False or 0 ,1
return userValue;
else return defaultValue;
}
}
var _uniqueMerge = function(opts, _ref){
for(var key in _ref)
if (_ref && _ref[key] && _ref[key].constructor && _ref[key].constructor === Object)
_ref[key] = _uniqueMerge((opts ? opts[key] : null ), _ref[key] );
else if(opts && opts.hasOwnProperty(key))
_ref[key] = _validation[_ref[key][0]](_ref[key][1], opts[key]); //or without validation on user enties => ref[key] = obj[key]
else _ref[key] = _ref[key][1];
return _ref;
}
var _get = function(inputs){
return _uniqueMerge(inputs, _defs());
}
return {
options: function(){
return _get(arguments[0] || null); // for more safety and control on number of input variables! used --> ( arguments[0] || null )
}
}
})();
//How to use it:
input_one = {
a : "Hello World",
//b : ["number", 400], //User missed this parameter
c: "Hi",
d : {
da : false,
db : "Hellow! World", // ! is not allowed
dc : {
dca : 10,
dcb : "My String",
dcc: "3thString",
dcd : false
},
dce: "ANOTHER STRING",
},
e: 40,
f: true,
z: 'x'
};
console.log( JSON.stringify( module.options(input_one), null ,2 ) );
//Output:
/*
{
"a": "Hello World",
"b": 300,
"c": true,
"d": {
"da": false,
"db": "Defaul value for \"db\"",
"dc": {
"dca": 10,
"dcb": "My String",
"dcc": 500,
"dcd": false
},
"dce": "ANOTHER STRING"
},
"e": 40,
"f": true,
"g": "This is an internal extra parameter"
}
*/
input_two = {
a : 32,
//b : ["number", 400], //User missed this parameter
c: "Hi",
d : {
da : false,
db : "HelloWorld",
dc : {
dca : 10,
dcb : "My String",
dcd : false
},
dce: 73,
}
};
console.log( JSON.stringify( module.options(input_two), null ,2 ) );
//output
/*
{
"a": "Defaul value for \"a\"",
"b": 300,
"c": true,
"d": {
"da": false,
"db": "HelloWorld",
"dc": {
"dca": 10,
"dcb": "My String",
"dcc": 500,
"dcd": false
},
"dce": "Default value for \"dce\""
},
"e": 200,
"f": 0,
"g": "This is an internal extra parameter"
}
*/
//Empty input will return the default values!
console.log( JSON.stringify( module.options(), null ,2 ) );
//Output
/*
{
"a": "Defaul value for \"a\"",
"b": 300,
"c": true,
"d": {
"da": true,
"db": "Defaul value for \"db\"",
"dc": {
"dca": 200,
"dcb": "Default value for \"dcb\"",
"dcc": 500,
"dcd": true
},
"dce": "Default value for \"dce\""
},
"e": 200,
"f": 0,
"g": "This is an internal extra parameter"
}
*/
</pre>
答案 65 :(得分:-1)
您可以在EcmaScript2016中执行以下操作
更正:这是第3阶段提案,但它一直对我有用
const objA = {
attrA: 'hello',
attrB: true
}
const objB = {
attrC: 2
}
const mergedObj = {...objA, ...objB}
答案 66 :(得分:-1)
function extend()
{
var o = {};
for (var i in arguments)
{
var s = arguments[i];
for (var i in s)
{
o[i] = s[i];
}
}
return o;
}
答案 67 :(得分:-2)
如果你需要一个深度合并,它也会&#34;合并&#34;通过在结果中连接它们的数组,那么这个ES6函数可能就是你所需要的:
var databaseRef = firebase.database().ref('messages');
var chatList = document.getElementById('chatList');
databaseRef.on('value', function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var node = document.createElement("li");
node.className="collection-repeat";
var textnode = document.createTextNode( childSnapshot.val().message );
node.appendChild(textnode);
chatList.appendChild(node);
})
});
&#13;
function deepMerge(a, b) {
// If neither is an object, return one of them:
if (Object(a) !== a && Object(b) !== b) return b || a;
// Replace remaining primitive by empty object/array
if (Object(a) !== a) a = Array.isArray(b) ? [] : {};
if (Object(b) !== b) b = Array.isArray(a) ? [] : {};
// Treat arrays differently:
if (Array.isArray(a) && Array.isArray(b)) {
// Merging arrays is interpreted as concatenation of their deep clones:
return [...a.map(v => deepMerge(v)), ...b.map(v => deepMerge(v))];
} else {
// Get the keys that exist in either object
var keys = new Set([...Object.keys(a),...Object.keys(b)]);
// Recurse and assign to new object
return Object.assign({}, ...Array.from(keys,
key => ({ [key]: deepMerge(a[key], b[key]) }) ));
}
}
// Sample data for demo:
var a = {
groups: [{
group: [{
name: 'John',
age: 12
},{
name: 'Mary',
age: 20
}],
groupName: 'Pair'
}],
config: {
color: 'blue',
range: 'far'
}
};
var b = {
groups: [{
group: [{
name: 'Bill',
age: 15
}],
groupName: 'Loner'
}],
config: {
range: 'close',
strength: 'average'
}
};
var merged = deepMerge(a, b);
console.log(merged);
&#13;
请注意,如果只有一个参数传递给此函数,则它将充当深度克隆函数。
答案 68 :(得分:-3)
使用object.assign
Object.prototype.assign = Object.assign && function () {
var a = [];
for (var _i = 0; _i < arguments.length; _i++) {
a[_i] = arguments[_i];
}
var src = a.slice(1);
var target = a[0];
for (var o in src) {
if (src.hasOwnProperty(o)) {
var keys = Object.keys(src[o]);
var _src = src[o];
for (var k in keys) {
if (keys.hasOwnProperty(k)) {
var _key = keys[k];
target[_key] = _src[_key];
}
}
}
}
return target;
};