展开运算符...是语法糖,用于将可迭代对象“打散”为独立元素,支持数组拼接、对象合并、函数传参等,但仅浅拷贝且要求操作对象可迭代。
JavaScript 展开运算符 ... 不是函数,也不是方法,而是一种语法糖——它把可迭代对象(比如数组、字符串、Set、Map)“打散”成独立元素,让数据操作更直觉。它和剩余参数(...rest)长得一样,但方向相反:一个是“拆”,一个是“收”。
[...arr1, ...arr2] 而不是 concat()?因为写法更紧凑、可读性更高,且支持在任意位置插入元素或字面量。
[...arr1, 99, ...arr2] 可直接在中间插值,concat() 做不到{ ...obj1, name: 'Alice', ...obj2 },后者同名属性自动覆盖前者null 或 undefined 直接展开,否则报 TypeError: Cannot spread non-iterable instance
Math.max(...nums) 比 apply() 好在哪?省去上下文绑定(null)、不用记 API,还能混搭其他参数。
const nums = [4, 2, 7]; Math.max(...nums); // ✅ 7 Math.max(0, ...nums, 10); // ✅ 支持混合写法:0, 4, 2, 7, 10 → 10 // 替代写法(已过时): Math.max.apply(null, nums); // ❌ 冗长,且无法混搭
reduce()
new Date(...[2025, 0, 1]) 等价于 new Date(2025, 0, 1)
[...arr] 和 {...obj} 容易忽略什么?它们只拷贝第一层,嵌套对象/数组仍共享引用——这不是 bug,是设计使然。
const original = [{ a: 1 }, [2, 3]];
const copy = [...original];
copy[0].a = 99;
console.log(original[0].a); // 99 ← 原数组被改了
structuredClone()(现代环境),或 JSON.parse(JSON.stringify(obj))(简单场景)document.querySelectorAll('div'))必须先转为真数组才能用 map/filter:[...nodeList].map(...)
{ ...(obj ?? {}) },避免 obj 为 null 时报错展开运算符的威力不在“多厉害”,而在“恰到好处”——它解决的都是日常高频小痛点:拼数组、传参数、
合并配置、解构剩余字段。但只要忘了它是浅拷贝,或对着 undefined 直接展开,错误就会立刻浮现。用之前,先问一句:我要展开的东西,真的可迭代吗?它的结构,我是否只动了第一层?