游乐游手机版
首页/前端开发/文章详情

JavaScript Object.assign合并嵌套对象的浅拷贝与深拷贝行为

时间:2026-07-08 06:55
Object assign仅进行浅拷贝,不递归合并嵌套对象,后出现的源对象会整体覆盖同名嵌套属性。引用类型复制地址,修改会影响原对象。属性值undefined会被写入,null作为源对象被忽略。实现深度合并需借助structuredClone或lodash merge。

Object.assign 方法虽然用起来很方便,但不少开发者在使用它合并嵌套对象时都遇到过问题——它本质上只做浅拷贝,并不会递归合并深层结构。简单来说,它只复制第一层属性,嵌套对象不会逐层合并,而是整个引用直接覆盖。如果不了解这一特性,在配置合并、状态更新等场景下很容易引发意外 bug。

Ja vaScript 中 Object.assign 在合并对象时的深度属性行为

换句话说,Object.assign 在对对象进行合并时仅处理顶层属性,不会递归合并深层嵌套。嵌套对象不会像期待的那样逐个字段叠加,而是整个引用被替换。如果对此没有清晰认知,在合并配置参数、更新应用状态等操作中极易埋下难以察觉的错误。

嵌套对象会被整体覆盖,而不是逐层合并

当多个源对象中包含同名的嵌套对象属性(例如 apiuser.profile),后面出现的源对象会直接覆盖前面的,内部字段不会叠加保留。

  • 举个具体例子:{ api: { baseUrl: '/v1' } }{ api: { timeout: 3000 } } 合并后,得到的结果是 { api: { timeout: 3000 } }baseUrl 会丢失。
  • 这不是子属性的合并,而是直接将整个对象引用赋值——操作简单粗暴,后果往往出乎意料。

所有引用类型都只复制内存地址

数组、日期对象、正则表达式、普通对象……只要属性值是引用类型,Object.assign 就只复制其内存地址,而不会创建新副本。这意味着,任意一处修改都会影响所有持有该引用的对象。

  • 例如:const a = { list: [1, 2] }; const b = Object.assign({}, a); b.list.push(3); → 结果 a.list 也会变成 [1, 2, 3]
  • 更深层的嵌套如 user.address.city 被修改时,同样会波及所有共享该引用的对象。

不会自动跳过 undefined 或 null 值

如果某个源对象的属性值为 undefined,它依然会被写入目标对象,将对应字段设为 undefinednull 的处理与之类似,但注意:null 作为整个源对象参数(而非属性值)时会被忽略。

  • Object.assign({x: 1}, {x: undefined}) → 结果是 {x: undefined}
  • Object.assign({x: 1}, null, {y: 2}) → 结果是 {x: 1, y: 2}null 源被自动跳过)

要实现深度合并,必须另寻方案

Object.assign 本身并不提供深度合并功能。如果需要嵌套对象的递归合并,可以参考以下做法:

  • 使用 structuredClone()(现代浏览器环境)先深度克隆对象,再执行合并
  • 借助 lodash.merge(),该方法会递归合并嵌套结构
  • 自行编写递归函数,灵活控制合并逻辑(例如跳过 undefined、保留默认值等)
来源:https://www.php.cn/faq/2747590.html
上一篇JavaScript async函数异常处理的覆盖范围详解 下一篇Bootstrap 4基于CSS的暗黑主题切换实现方案
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
深入理解调用栈与异步任务的状态同步机制
前端开发 · 2026-07-08

深入理解调用栈与异步任务的状态同步机制

调用栈仅记录同步执行流,异步回调由事件循环调度、任务队列存放,闭包维持作用域。执行时新建上下文入栈,不复用旧栈帧。调用栈不主动同步异步状态,事件循环是真正的协调者。

HTML自定义元素实现跨组件通信的完整指南
前端开发 · 2026-07-08

HTML自定义元素实现跨组件通信的完整指南

自定义元素跨组件通信需依赖CustomEvent,且bubbles和composed必须同时设为true才能穿透ShadowDOM。事件监听应挂载在document或父容器等合适节点,避免使用DOM查找或data ARIA属性替代事件通信,从而确保事件正确穿越边界,保持跨组件通信的可靠性。

JavaScript static关键字在工具库构建中的应用
前端开发 · 2026-07-08

JavaScript static关键字在工具库构建中的应用

在JavaScript工具库构建中,static关键字将函数或常量挂载到类名上,无需实例化即可调用,适用于无状态操作如日期格式化、字符串截断、深克隆,并统一管理配置常量与实现工厂方法,但需避免依赖实例状态。

如何避免静态初始化块异常导致应用冷启动中断
前端开发 · 2026-07-08

如何避免静态初始化块异常导致应用冷启动中断

防范静态初始化失败导致应用中断,需用try-catch兜住异常并提供安全默认值;将高风险逻辑移出static块,改用延迟加载或Holder模式;显式控制初始化顺序并增强可观测性;诊断时直击ExceptionInInitializerError的根因。

虚拟DOM标签级diff比对优化过程详解
前端开发 · 2026-07-08

虚拟DOM标签级diff比对优化过程详解

虚拟DOMdiff以节点为单位,按层级同标签优先判断复用,通过key精准识别节点身份,配合细粒度属性更新及短路优化,避免全量递归比较,只更新变化的节点,跳过冗余计算,将时间复杂度从O(n³)降至接近O(n),从而大幅提升渲染性能。