You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优雅更新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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:57:32