如何实现JavaScript对象深度扩展?Object.assign仅支持顶层扩展
如何实现对象的深度扩展(保留嵌套属性)
你提到的问题正是Object.assign()的局限性——它是浅合并:当遇到嵌套对象时,它会直接用新对象替换掉原有的子对象,而不会递归合并内部的属性。所以你看到params整个被替换,导致原来的params.data和params.page.b都丢失了。
下面给你几种实用的解决方案:
方案1:针对已知结构,用展开运算符逐层合并
如果你的对象结构是确定的,这种方式最直观,也不需要额外写工具函数。通过ES6的展开运算符(...)逐层展开嵌套对象,只修改需要更新的属性,其他属性会自动保留:
const source = { id: 1, otherKey: {}, params: { page: { a: 1, b: {} }, data: { b: 1 } } }; const result = { ...source, // 展开顶层属性 params: { ...source.params, // 保留原params的所有属性 page: { ...source.params.page, // 保留原page的所有属性 a: 2 // 只更新a的值 } } }; console.log(result); // 输出: // { // id: 1, // otherKey: {}, // params: { // page: { a: 2, b: {} }, // data: { b: 1 } // } // }
这种方式的好处是代码清晰,你能明确看到哪些属性被修改,哪些被保留,适合结构固定的场景。
方案2:实现通用的深合并函数
如果你的对象结构不确定,或者需要频繁处理深合并,可以写一个通用的递归深合并函数,它会自动遍历所有嵌套对象,合并而不是替换:
// 判断是否为纯对象(排除数组、null等) function isObject(item) { return item && typeof item === 'object' && !Array.isArray(item); } // 深合并函数:将多个源对象合并到目标对象 function deepMerge(target, ...sources) { if (!sources.length) return target; const currentSource = sources.shift(); if (isObject(target) && isObject(currentSource)) { for (const key in currentSource) { // 如果当前属性是对象,递归合并 if (isObject(currentSource[key])) { // 如果目标对象没有这个属性,先初始化一个空对象 if (!target[key]) Object.assign(target, { [key]: {} }); deepMerge(target[key], currentSource[key]); } else { // 非对象属性直接赋值 Object.assign(target, { [key]: currentSource[key] }); } } } // 递归处理剩下的源对象 return deepMerge(target, ...sources); } // 使用示例 const source = { id: 1, otherKey: {}, params: { page: { a: 1, b: {} }, data: { b: 1 } } }; const result = deepMerge({}, source, { params: { page: { a: 2 } } }); console.log(result); // 输出和方案1一致,保留了所有嵌套属性
这个函数可以处理任意深度的对象合并,而且会自动保留未被修改的嵌套属性,适合通用场景。
方案3:使用第三方库(可选)
如果你不想自己写函数,也可以用成熟的第三方库,比如Lodash的_.merge()方法,它就是专门做深合并的:
// 先安装lodash:npm install lodash const _ = require('lodash'); const source = { id: 1, otherKey: {}, params: { page: { a: 1, b: {} }, data: { b: 1 } } }; const result = _.merge({}, source, { params: { page: { a: 2 } } });
不过如果项目中没有引入Lodash,方案1或2会更轻量。
内容的提问来源于stack exchange,提问作者undefined
相关产品推荐
相关产品推荐

