合并两个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()
方法进行过滤。对象引用问题 :一些合并方法会修改原对象,需要注意是否需要创建新对象来避免影响原对象。