二十、Object.assign() 方法:
1. 基本语法
Object.assign 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
javascript
Object.assign(target, ...sources)
- target(目标对象):必需。接收属性的对象。
- sources(源对象):可选。一个或多个源对象,它们的属性将被复制到目标对象。
核心规则:
- 如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。
- 后面的源对象的属性将类似地覆盖前面的源对象的属性。
2. 基础示例
(1) 基本合并
javascript
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target); // 输出: { a: 1, b: 4, c: 5 }
console.log(returnedTarget === target); // 输出: true (返回的是同一个对象引用)
(2) 合并多个对象
javascript
const obj1 = { a: 1 };
const obj2 = { b: 2 };
const obj3 = { c: 3 };
const merged = Object.assign({}, obj1, obj2, obj3);
console.log(merged); // 输出: { a: 1, b: 2, c: 3 }
小技巧 :如果不希望修改原对象,通常将 target 设为一个空对象 {}。
示例:

3. 企业开发中的实际应用场景
场景一:组件默认配置与用户自定义配置合并
这是 Object.assign 最经典的用法。开发通用组件(如弹窗、表格)时,通常有一份默认配置,用户传入的配置需要覆盖默认值。
javascript
// 默认配置
const defaultOptions = {
width: 100,
height: 50,
color: 'blue',
draggable: false
};
// 用户传入的自定义配置
const userOptions = {
width: 200,
color: 'red'
};
// 合并策略:创建一个新对象,先放入默认值,再覆盖用户值
const finalOptions = Object.assign({}, defaultOptions, userOptions);
console.log(finalOptions);
// 输出: { width: 200, height: 50, color: 'red', draggable: false }
场景二:Redux/State 状态更新(不可变数据)
在 Redux 或 React 的 Class 组件时代,我们不能直接修改 state,而是需要返回一个新的对象。Object.assign 是实现浅拷贝更新的标准写法。
javascript
const initialState = {
loading: false,
data: [],
error: null
};
// 模拟 Reducer 中的状态更新
function reducer(state = initialState, action) {
switch (action.type) {
case 'FETCH_START':
// 返回一个新对象,保持原 state 不变
return Object.assign({}, state, {
loading: true
});
case 'FETCH_SUCCESS':
return Object.assign({}, state, {
loading: false,
data: action.payload
});
default:
return state;
}
}
场景三:为对象动态添加属性与方法
虽然可以直接 obj.key = value,但在批量添加或需要保持代码整洁时,Object.assign 很有用。
javascript
class User {
constructor(name) {
this.name = name;
}
}
// 动态混入功能(类似于 Mixin 模式)
const features = {
sayHello() {
console.log(`Hello, I'm ${this.name}`);
},
walk() {
console.log(`${this.name} is walking`);
}
};
const user = new User('Jack');
Object.assign(user, features);
user.sayHello(); // 输出: Hello, I'm Jack
4. 注意事项
(1) 浅拷贝------ 最大的坑
这是新手最容易犯的错误。Object.assign 只能拷贝第一层属性。如果源对象的属性值是一个对象(引用类型),拷贝的是该对象的引用。
javascript
const source = {
a: 1,
b: {
c: 2
}
};
const target = Object.assign({}, source);
// 修改 target 中嵌套对象的值
target.b.c = 100;
// 悲剧发生了:源对象也被修改了!
console.log(source.b.c); // 输出: 100
避坑指南 :对于深层对象结构,推荐使用 JSON.parse(JSON.stringify(obj)) 进行深拷贝(注意函数和 undefined 会丢失),或使用 Lodash 的 _.cloneDeep。
(2) 同名属性的完全覆盖
不仅是值会被覆盖,属性描述符也会被覆盖。
javascript
const source = Object.defineProperty({}, 'name', {
value: 'Source',
writable: false // 不可写
});
const target = { name: 'Target' };
Object.assign(target, source);
// assign 只拷贝值,不拷贝属性描述符
// target.name 变成了 'Source',但 writable 特性并未复制过来,而是恢复默认
console.log(target.name); // 'Source'
(3) 数组的处理
如果参数是数组,Object.assign 会把数组视为对象处理,键名是索引。
javascript
const arr1 = [1, 2, 3];
const arr2 = [4, 5];
const result = Object.assign(arr1, arr2);
console.log(result); // 输出: [4, 5, 3] (不是合并数组,而是属性覆盖)
// 解释: arr2 的 '0':4 覆盖了 arr1 的 '0':1, '1':5 覆盖了 '2':2,'3'未受影响
避坑指南 :合并数组请使用 [...arr1, ...arr2] 或 arr1.concat(arr2)。