合并两个JavaScript对象属性的方法

合并两个JavaScript对象属性的方法

技术背景

在JavaScript开发中,经常会遇到需要合并两个或多个对象属性的场景。例如,将默认配置对象和用户自定义配置对象合并,或者将多个数据源的对象合并成一个对象。不同的JavaScript版本和工具提供了多种合并对象属性的方法。

实现步骤

ECMAScript 2018标准方法

使用对象展开语法(object spread):

1
let merged = {...obj1, ...obj2};
JAVASCRIPT

这种方法会将obj2的属性合并到obj1的属性上,如果有相同的属性名,obj2的属性值会覆盖obj1的属性值。可以合并任意数量的对象,后面对象的属性会覆盖前面对象相同名称的属性。

1
const allRules = {...obj1, ...obj2, ...obj3};
JAVASCRIPT

如果使用Babel,需要安装@babel/plugin-proposal-object-rest-spread插件(该插件包含在@babel/preset-env中)。

ECMAScript 2015 (ES6)标准方法

使用Object.assign()方法:

1
Object.assign(obj1, obj2);
JAVASCRIPT

Object.assign()方法用于将一个或多个源对象的所有可枚举自有属性复制到目标对象,并返回目标对象。也可以合并任意数量的对象,所有对象都会合并到第一个对象中,只有第一个参数的对象会被修改并返回。

1
const allRules = Object.assign({}, obj1, obj2, obj3);
JAVASCRIPT

ES5及更早版本的方法

使用for...in循环:

1
2
3
for (var attrname in obj2) { 
obj1[attrname] = obj2[attrname];
}
JAVASCRIPT

这种方法会将obj2的所有属性添加到obj1中,如果还需要使用未修改的obj1,可能需要创建一个新对象。

1
2
3
4
5
6
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;
}
JAVASCRIPT

递归合并方法

当对象的属性值也是对象时,需要进行递归合并:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function MergeRecursive(obj1, obj2) {
for (var p in obj2) {
try {
if ( obj2[p].constructor==Object ) {
obj1[p] = MergeRecursive(obj1[p], obj2[p]);
} else {
obj1[p] = obj2[p];
}
} catch(e) {
obj1[p] = obj2[p];
}
}
return obj1;
}
JAVASCRIPT

使用第三方库

  • jQuery:使用jQuery.extend()方法。
1
2
3
var settings = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };
jQuery.extend(settings, options);
JAVASCRIPT

如果要创建一个新对象而不修改任何参数,可以这样使用:

1
2
3
var defaults = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };
var settings = $.extend({}, defaults, options);
JAVASCRIPT
  • lodash:提供了_.extend()_.merge()方法。
1
_.extend({name : 'moe'}, {age : 50});
JAVASCRIPT
  • deepmerge:一个独立的库,可通过npm和bower包管理器获取。

核心代码

自定义合并函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
};
JAVASCRIPT

支持任意数量对象的递归合并函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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;
}
JAVASCRIPT

最佳实践

  • 优先使用ES2018的对象展开语法或ES2015的Object.assign()方法,因为它们简洁且性能较好。
  • 如果需要递归合并对象属性,使用递归合并函数。
  • 在使用第三方库时,确保项目中已经正确引入该库。

常见问题

  • 兼容性问题:ES2015和ES2018的方法在旧浏览器中可能不支持,可以使用polyfill来解决。
  • 原型链属性问题:在使用for...in循环时,可能会复制原型链上的属性,建议使用hasOwnProperty()方法进行过滤。
  • 对象引用问题:一些合并方法会修改原对象,需要注意是否需要创建新对象来避免影响原对象。

合并两个JavaScript对象属性的方法
https://119291.xyz/posts/merge-properties-of-two-javascript-objects/
作者
ww
发布于
2025年5月9日
许可协议