ES6 扩展运算符的基本概念

扩展运算符(...)是 ES6 引入的一种语法,用于将可迭代对象(如数组、字符串、对象等)的元素展开到指定位置。它的主要作用是将集合中的元素拆分为独立项,方便在函数调用、数组构造或对象构造时使用。


扩展运算符的常见用法

数组展开

const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]

扩展运算符可以快速合并数组,避免使用 concat 方法。

函数参数传递

function sum(a, b, c) {
  return a + b + c;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers)); // 6

将数组展开为函数的参数列表,替代传统的 apply 方法。

对象展开

const obj1 = { x: 1, y: 2 };
const obj2 = { ...obj1, z: 3 }; // { x: 1, y: 2, z: 3 }

在对象字面量中使用扩展运算符可以浅拷贝或合并对象,但需要注意属性覆盖问题。


扩展运算符的注意事项

  • 浅拷贝问题:扩展运算符对对象或数组的拷贝是浅层的,嵌套结构仍会共享引用。
  • 可迭代对象:只能用于可迭代对象(如数组、字符串、MapSet 等),不可直接用于普通对象(需 ES2018 支持对象扩展)。
  • 函数调用顺序:在函数调用时,扩展运算符需放在参数列表的最后。

扩展运算符的实际应用场景

复制数组或对象

const original = [1, 2, 3];
const copy = [...original];

合并多个对象

const defaults = { mode: 'light', size: 10 };
const userSettings = { size: 20 };
const finalSettings = { ...defaults, ...userSettings }; // { mode: 'light', size: 20 }

字符串转数组

const str = 'hello';
const chars = [...str]; // ['h', 'e', 'l', 'l', 'o']


扩展运算符与剩余参数的区别

扩展运算符用于展开元素,而剩余参数(Rest Parameters)用于收集剩余元素到数组:

function logArgs(first, ...rest) {
  console.log(first); // 1
  console.log(rest);  // [2, 3]
}
logArgs(1, 2, 3);

剩余参数必须在参数列表末尾,且一个函数只能有一个剩余参数。


注意事项

  1. 浅拷贝问题:扩展运算符仅执行浅拷贝,嵌套对象或数组仍保留引用。

    const nested = { a: { b: 1 } };
    const shallowCopy = { ...nested };
    shallowCopy.a.b = 2; // 原对象也会被修改

  2. 不可迭代对象:尝试展开非可迭代对象(如普通对象在旧版JavaScript中)会报错,需确保环境支持对象展开(ES2018+)。

  3. 性能考量:频繁展开大型数组或对象可能影响性能,需结合场景评估。

优化与建议

  1. 深拷贝场景:结合JSON.parse(JSON.stringify())或工具库(如Lodash的_.cloneDeep)处理嵌套结构。

  2. 替代arguments对象:在函数中使用剩余参数(Rest Parameters)代替arguments

    function logArgs(...args) {
      console.log(args); // 直接获得数组
    }

  3. 代码可读性:避免过度嵌套展开运算符,保持逻辑清晰。例如:

    // 不推荐
    const complex = { ...{ ...obj1, ...obj2 }, ...obj3 };

总结

ES6扩展运算符简化了数组和对象的操作,支持快速合并、复制及参数传递,但需注意浅拷贝和兼容性问题。合理使用能提升代码简洁性,但在复杂场景需结合深拷贝或其他工具库。