在 JavaScript 中,扩展运算符(Spread Operator) 是 ES6 引入的一个非常实用的语法特性,它可以将数组、对象、字符串等“展开”为多个元素或属性。它极大地简化了代码书写,提升了可读性和开发效率。
✅ 一句话总结
扩展运算符
...可以将一个可迭代对象(如数组、对象、字符串等)展开为多个值,常用于合并、复制、解构数组和对象,以及函数调用时传参等场景。
✅ 一、对象中的扩展运算符(...)
🔹 基本作用:
将一个对象的所有可枚举自有属性展开到另一个对象中。
const bar = { a: 1, b: 2 };
const baz = { ...bar }; // 等价于 Object.assign({}, bar)
console.log(baz); // { a: 1, b: 2 }
🔹 合并对象(后覆盖前)
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const merged = { ...obj1, ...obj2 };
console.log(merged); // { a: 1, b: 3, c: 4 }
📌 特点:
- 属性按顺序展开,后面的会覆盖前面的;
- 不包括继承来的属性;
- 不复制 Symbol 类型的键;
- 浅拷贝:如果对象中包含嵌套对象,它们仍然是引用;
🔹 Redux 中的应用示例
在 Redux 的 reducer 函数中要求不能直接修改 state,可以使用扩展运算符创建新对象:
function userReducer(state = { name: 'Tom', age: 20 }, action) {
switch (action.type) {
case 'UPDATE_AGE':
return { ...state, age: action.payload };
default:
return state;
}
}
✅ 二、数组中的扩展运算符(...)
🔹 基本作用:
将数组转换为逗号分隔的参数序列,每次只能展开一层。
console.log(...[1, 2, 3]); // 输出:1 2 3
console.log(...[1, [2, 3], 4]); // 输出:1 [2, 3] 4
🔹 使用场景
1️⃣ 将数组作为参数传给函数
function add(x, y) {
return x + y;
}
const numbers = [1, 2];
console.log(add(...numbers)); // 3
2️⃣ 复制数组(浅拷贝)
const arr1 = [1, 2];
const arr2 = [...arr1]; // 浅拷贝
3️⃣ 合并数组
const arr1 = ['two', 'three'];
const arr2 = ['one', ...arr1, 'four', 'five'];
console.log(arr2); // ["one", "two", "three", "four", "five"]
4️⃣ 解构赋值 + 扩展运算符
const [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest); // [2, 3, 4, 5]
⚠️ 注意:
扩展运算符只能出现在解构表达式的最后位置,否则会报错:
const [...rest, last] = [1, 2, 3]; // ❌ 报错
5️⃣ 字符串转为数组
console.log([...'hello']); // ['h', 'e', 'l', 'l', 'o']
6️⃣ 转换类数组对象为数组(如 arguments)
function foo() {
const args = [...arguments];
console.log(args);
}
foo(1, 2, 3); // [1, 2, 3]
替代 ES5 写法:
Array.prototype.slice.call(arguments);
7️⃣ 数组去重 + Math 方法结合使用
const numbers = [10, 5, 8, 12, 3];
console.log(Math.max(...numbers)); // 12
console.log([...new Set(numbers)]); // 去重后的数组
✅ 三、常见误区与注意事项
| 注意事项 | 说明 |
|---|---|
| 只展开一层 | 对于嵌套数组或对象,只会浅层展开 |
| 不复制 Symbol 键 | 如果对象中有 Symbol 类型的 key,不会被复制 |
| 不能展开不可遍历对象 | 如 null、undefined、数字等,会抛出错误 |
| 对象合并是后覆盖前 | 注意合并顺序对结果的影响 |
✅ 四、一句话总结
扩展运算符
...是现代 JavaScript 开发中不可或缺的工具,适用于数组复制、合并、解构、函数传参、对象合并等多种场景。但要注意它是浅拷贝,对于嵌套结构需要配合深拷贝方法使用。
💡 进阶建议
- 在 Vue / React 开发中,推荐使用扩展运算符更新状态对象,保持不可变性;
- 结合
immer.js实现更安全的状态更新; - 使用 TypeScript 可以更好地推导类型和防止误操作;
- 使用 ESLint 规则避免在解构中滥用扩展运算符导致性能问题;