前端开发中的常用工具函数(八)

前端开发中的常用工具函数(八)
二十、Object.assign() 方法1. 基本语法Object.assign方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。Object.assign(target, ...sources)target目标对象必需。接收属性的对象。sources源对象可选。一个或多个源对象它们的属性将被复制到目标对象。核心规则如果目标对象中的属性具有相同的键则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性。2. 基础示例(1) 基本合并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) 合并多个对象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最经典的用法。开发通用组件如弹窗、表格时通常有一份默认配置用户传入的配置需要覆盖默认值。// 默认配置 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是实现浅拷贝更新的标准写法。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很有用。class User { constructor(name) { this.name name; } } // 动态混入功能类似于 Mixin 模式 const features { sayHello() { console.log(Hello, Im ${this.name}); }, walk() { console.log(${this.name} is walking); } }; const user new User(Jack); Object.assign(user, features); user.sayHello(); // 输出: Hello, Im Jack4. 注意事项(1) 浅拷贝—— 最大的坑这是新手最容易犯的错误。Object.assign只能拷贝第一层属性。如果源对象的属性值是一个对象引用类型拷贝的是该对象的引用。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) 同名属性的完全覆盖不仅是值会被覆盖属性描述符也会被覆盖。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会把数组视为对象处理键名是索引。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:23未受影响避坑指南合并数组请使用[...arr1, ...arr2]或arr1.concat(arr2)。