引言:为什么对象合并是每个 JavaScript 开发者的痛点
想象一下:你正在开发一个应用程序,需要合并来自两个不同来源的数据。例如,你有一个来自数据库的用户基本配置,以及来自前端的设置。如何在不痛苦和煎熬的情况下将它们合并?正是这个问题——“How can I merge properties of two JavaScript objects?”——在 Stack Overflow 上获得了数千次浏览。这并非偶然:JavaScript 中的对象合并隐藏着许多陷阱。
在本文中,我们将探讨所有流行的 JS 对象合并方法:从经典的 Object.assign() 到现代的展开运算符。您将学习如何深度复制嵌套结构、避免修改原始数据,以及根据您的任务选择正确的方法。开始吧!
问题:什么是“合并两个对象的属性”?
当我们说 “merge objects JavaScript” 时,我们指的是创建一个新对象,该对象包含来自原始对象的所有属性。如果遇到相同的键——第二个对象中的值会“覆盖”第一个对象中的值。
假设有两个对象:
const user = { name: '安娜', age: 28, city: '莫斯科'};
const updates = { age: 29, job: '开发者'};在 JS 对象合并之后,我们希望得到:
{ name: '安娜', age: 29, // 更新后的值 city: '莫斯科', job: '开发者' // 新属性}看起来很简单。但细节决定成败:嵌套对象、数组、原始对象的修改以及性能。
方法 1:Object.assign() —— 经典可靠的老方法
Object.assign() 方法是 JavaScript 对象合并中最古老且经过验证的方式。它将一个或多个源对象中所有可枚举的自有属性复制到目标对象。
语法
Object.assign(target, ...sources)重要提示:第一个参数是目标对象,它将被修改。所有后续参数是属性的来源。
合并示例
const user = { name: '安娜', age: 28 };const updates = { age: 29, job: '开发者' };
const merged = Object.assign({}, user, updates);console.log(merged);// { name: '安娜', age: 29, job: '开发者' }请注意:我们将一个空对象 {} 作为 target 传递。这确保了原始对象不会被修改——JS 对象克隆得以正确执行。
陷阱:浅拷贝
Object.assign() 只执行浅拷贝 (shallow copy)。如果您有嵌套对象,它们将通过引用进行复制:
const obj1 = { data: { value: 10 } };const obj2 = { info: 'test' };
const merged = Object.assign({}, obj1, obj2);merged.data.value = 999;console.log(obj1.data.value); // 999 —— 原始对象被修改!对于深度合并,我们需要其他方法,我们将在下面讨论。
方法 2:展开运算符 —— ES6 的优雅
随着 ES6 的出现,JavaScript 展开运算符(三个点 ...)成为了 合并对象属性最流行的方法。它简洁、易读,并且无需调用方法。
语法
const merged = { ...obj1, ...obj2 };示例
const defaults = { theme: 'light', lang: 'ru', showSidebar: true };const userPrefs = { theme: 'dark', fontSize: 16 };
const settings = { ...defaults, ...userPrefs };console.log(settings);// { theme: 'dark', lang: 'ru', showSidebar: true, font