1. 对象扩展的两种核心方式
在JavaScript开发中,对象合并与属性复制是日常高频操作。当我们需要组合配置项、合并状态或创建对象副本时,通常会面临两种主流方案的选择:扩展运算符(...)和Object.assign()。这两种语法虽然最终都能实现对象属性的合并,但在底层实现、使用场景和性能表现上存在显著差异。
最近在重构一个前端项目的状态管理模块时,我不得不对300多处对象操作进行标准化改造。最初代码中混用了...和Object.assign(),导致打包体积异常增大、部分页面渲染性能下降。通过系统对比测试,最终梳理出这套选择标准,现在团队代码规范中已明确规定不同场景下的首选方案。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 语法特性深度对比
2.1 扩展运算符的工作机制
扩展运算符的语法形式是在对象字面量中使用...obj,这实际上触发了ES6规范的Iterator协议。当引擎遇到...时:
- 首先检查对象是否实现[Symbol.iterator]
- 对于普通对象,会枚举所有可枚举属性(包括原型链)
- 按属性插入顺序将键值对展开到新对象
- 同名属性后者覆盖前者
javascript复制const defaults = { theme: 'light', fontSize: 14 }
const userSettings = { fontSize: 16, darkMode: true }
// 展开过程相当于:
const merged = {
theme: 'light', // 来自defaults
fontSize: 16, // userSettings覆盖了defaults的值
darkMode: true // 来自userSettings
}
关键细节:虽然规范要求保持属性顺序,但在某些JavaScript引擎中,动态添加的属性可能出现顺序不一致的情况,这在依赖属性顺序的场景(如CSS-in-JS)需要特别注意。
2.2 Object.assign的内部原理
Object.assign的工作方式更像传统属性拷贝:
- 第一个参数是目标对象(会被修改)
- 后续参数提供源对象
- 仅拷贝源对象自身的可枚举属性(忽略原型链)
- 同样采用后者覆盖前者的策略
jav复制
