六维教程

ES6 运算符扩展

之前讲函数里的 rest 参数,... 负责”把参数收集成数组”,现在轮到它相反的身份出场:展开运算符——把数组或对象”拆开展开”。

本篇以展开运算符为主角,同时收录两个日常高频、写法相关的运算符:可选链 ?. 和空值合并 ??(ES2020 推出,已广泛使用)。

展开运算符 ...

展开数组

把数组的元素”摊出来”,一个个传给函数或放进新数组:

// 示例:不用 apply,直接展开传给 Math.max
const nums = [3, 1, 4, 1, 5];
console.log(Math.max(...nums)); // 5

// 示例:合并数组
const a = [1, 2];
const b = [3, 4];
console.log([...a, ...b]);      // [1, 2, 3, 4]

对比记忆:rest 参数把”散开的参数收到一起”,展开运算符把”数组摊开”。长相一样、方向相反。

复制与展开对象

展开运算符也能用于对象,非常适合”合并或浅拷贝对象”:

// 示例:复制对象(浅拷贝)
const base = { name: '小明', age: 20 };
const copy = { ...base };
console.log(copy); // { name: '小明', age: 20 }

// 示例:合并对象,后面的会覆盖同名键
const extra = { age: 30, city: '北京' };
const merged = { ...base, ...extra };
console.log(merged); // { name: '小明', age: 30, city: '北京' }

注意:展开对象是浅拷贝,只复制一层;嵌套的对象仍然共享同一个引用。

可选链 ?.(ES2020)

访问嵌套属性时,中间某级可能是 undefinednull,直接 . 会报错:

// 示例:如果 type 不存在,直接访问会报错
// user.profile.address.city —— 如果 profile 不存在就报 TypeError

可选链 ?. 遇到中间为 undefined/null短路返回 undefined,不报错:

// 示例
const user = {};                      // 没有 profile
console.log(user.profile?.city);       // undefined —— 不报错
console.log(user.profile?.list[0]);    // undefined

常见场景:接口返回的数据字段可能缺失时很安全。Vue 模板里 v-for 数据对象、组件 props 上也很常用。

空值合并 ??(ES2020)

当左边的值是 null undefined 时,才返回右边的默认值:

// 示例
const a = null;
const b = undefined;
const c = 0;
console.log(a ?? '默认');  // 默认
console.log(b ?? '默认');  // 默认
console.log(c ?? '默认');  // 0  —— 注意:0 不是 null/undefined,保留

对比 ||0''false 这样”为假但合法”的值,|| 会错误地走默认值分支,?? 更符合直觉。

// 示例:0 被空值合并保留,不会丢失
console.log(0 || 100);   // 100 —— 被 || 吞了
console.log(0 ?? 100);   // 0   —— ?? 留给 0

注意:?? 不能直接和 ||&& 混放在同一个表达式里,需要括号分开。

三个运算符的常见用途

场景 用法
展开参数调用 fn(...arr)
合并数组 [...a, ...b]
复制数组 [...a]
合并对象 {...a, ...b}
复制对象 {...obj}
安全取值 obj?.a?.b
默认值 x ?? 默认值

掌握这三个运算符后,你写代码时很多”不敢写死”的地方都可以大胆放心写。

上一篇
ES6 解构赋值
下一篇
ES6 Symbol