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

如何实现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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:09:50