如何优雅更新JavaScript深层嵌套对象且不覆盖原有属性?
如何优雅地深层合并嵌套对象而不覆盖原有属性?
这个问题我之前也碰到过!Object.assign和扩展运算符(...)确实只能处理浅层次的对象合并,当遇到嵌套的子对象时,它们会直接用源对象的子对象替换目标对象的对应子对象,而不会递归合并内部属性。要实现你想要的效果,有两种实用方案:
方案一:手动实现递归合并函数
如果不想引入第三方依赖,自己写一个递归合并的函数就能解决问题。这个函数会遍历对象的每个属性,遇到嵌套对象时就递归处理,而非直接替换:
function deepMerge(target, source) { // 处理非对象或null的情况 if (typeof target !== 'object' || target === null) return target; if (typeof source !== 'object' || source === null) return source; // 遍历源对象的所有可枚举属性 for (const key in source) { if (source.hasOwnProperty(key)) { // 若目标和源的当前属性都是对象,则递归合并 if (typeof target[key] === 'object' && typeof source[key] === 'object') { // 先复制目标对象的当前属性,避免修改原数据 target[key] = deepMerge({...target[key]}, source[key]); } else { // 非对象属性直接覆盖 target[key] = source[key]; } } } return target; } // 测试你的示例 const data = { items: { one: { active: false, id: '123' }, two: { active: true } } }; const updatedData = { items: { one: { active: true } } }; const finalResult = deepMerge({...data}, updatedData); console.log(finalResult); // 输出:{ items: { one: { active: true, id: '123' }, two: { active: true } } }
注意这里我们在合并前用{...target[key]}复制了目标对象的属性,这样不会修改原始的data对象,保证数据的不可变性。
方案二:使用成熟的第三方库(推荐)
如果你的项目已经在使用工具库,比如Lodash,那直接用它的_.merge方法是最省心的选择——这个方法就是专门为深层合并对象设计的,经过了充分的测试:
const _ = require('lodash'); const data = { items: { one: { active: false, id: '123' }, two: { active: true } } }; const updatedData = { items: { one: { active: true } } }; const finalResult = _.merge({}, data, updatedData); console.log(finalResult); // 同样得到你期望的结果
_.merge会递归地将源对象的属性合并到目标对象中,只覆盖冲突的属性,保留所有未被修改的原有属性,完全符合你的需求。
内容的提问来源于stack exchange,提问作者dzm
相关产品推荐
相关产品推荐

