可选链
JavaScript 可选链(Optional Chaining)笔记
一、可选链的引入背景与核心问题(对应视频 00:00-03:15)
1.1 传统属性访问的痛点
当访问嵌套对象的属性时,若中间某一层属性不存在(值为undefined或null),直接访问会触发类型错误。
-
示例场景:获取餐厅(
restaurant
)周一(
1
mon
)的营业时间(
1
open
),对象结构如下:
javascript
1
2
3
4
5
6
7const restaurant = {
openingHours: {
thu: { open: 12, close: 22 },
fri: { open: 11, close: 23 },
sat: { open: 0, close: 24 }, // 0表示24小时营业
},
}; -
问题代码:直接访问
1
restaurant.openingHours.mon.open
由于
1
openingHours
中没有
1
mon
属性,
1
restaurant.openingHours.mon
会返回
1
undefined
,后续访问
1
open
会报错:
1
Uncaught TypeError: Cannot read properties of undefined (reading 'open')
。
1.2 传统解决方案的局限性
为避免报错,需手动逐层检查属性是否存在,代码冗余且可读性差,嵌套层级越多,问题越突出。
-
传统写法:
javascript
1
2
3
4
5
6// 需先检查openingHours存在,再检查mon存在
if (restaurant.openingHours && restaurant.openingHours.mon) {
console.log(restaurant.openingHours.mon.open);
} else {
console.log("Closed");
} -
缺点:若嵌套层级增加(如
restaurant.location.address.city),需叠加更多条件判断,代码臃肿。
二、可选链的基本概念与语法(对应视频 03:16-06:25)
2.1 定义与语法
-
定义:可选链(
?.)是 ES2020 引入的特性,用于安全访问嵌套对象 / 数组的属性或方法。若?.左侧的表达式值为null或undefined(即 “空值”),则立即返回undefined,不再继续访问后续属性,避免报错。 -
语法规则
:
- 访问对象属性:
obj?.prop(等价于obj && obj.prop,但更简洁) - 访问嵌套属性:
obj?.prop1?.prop2(支持多层嵌套,任意一层为空则返回undefined) - 动态属性访问:
obj?.[dynamicProp](结合括号表示法,支持变量作为属性名)
- 访问对象属性:
2.2 基础使用示例
基于 1.1 中的restaurant对象,用可选链优化属性访问:
javascript
1 | // 1. 访问单层可选属性:检查openingHours是否存在,再访问mon |
2.3 关键注意点
- 可选链仅判断 “空值”(
null/undefined),对0、''、false等 “假值” 不生效,仍会继续访问后续属性。 - 示例:
restaurant.openingHours?.sat?.open返回0(0是有效值,非空值),而非undefined。
三、可选链在动态场景中的应用(对应视频 06:26-10:59)
3.1 动态属性访问(结合数组与变量)
当属性名通过变量动态生成(如从数组中获取)时,需用?.[变量]语法,可选链同样适用。
-
示例场景:循环数组
1
weekdays
,获取餐厅每天的营业时间:
javascript
1
2
3
4
5
6
7const weekdays = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"];
weekdays.forEach((day) => {
// 动态访问:day为变量,用?.[day]检查属性是否存在
const open = restaurant.openingHours?.[day]?.open ?? "Closed";
console.log(`${day}: ${open}`);
}); -
输出结果:
plaintext
1
2
3
4
5
6
7mon: Closed
tue: Closed
wed: Closed
thu: 12
fri: 11
sat: 0
sun: Closed
3.2 对比传统写法
若不用可选链,需手动检查openingHours和[day]是否存在,代码如下:
javascript
1 | weekdays.forEach((day) => { |
- 结论:可选链将 3 行判断简化为 1 行,代码更简洁,可读性更高。
四、可选链与空值合并运算符的配合(对应视频 10:00-11:15)
4.1 为何需要搭配使用
- 问题:若用
||设置默认值,会误将0、''等 “假值” 当作 “空值” 处理。例如restaurant.openingHours.sat.open为0,用||会返回默认值'Closed',与实际业务逻辑冲突。 - 解决方案:空值合并运算符(
??)仅在左侧为null/undefined时返回右侧默认值,与可选链搭配可精准处理默认值场景。
4.2 实战示例
javascript
1 | // 错误写法:用||,sat的open=0会被当作假值,返回'Closed' |
4.3 常见使用场景
- 接口数据处理:当接口返回的嵌套字段可能缺失时,用
obj?.field1?.field2 ?? '默认值'确保代码不报错且显示合理。 - 表单值获取:
input?.value ?? ''(避免input元素未渲染时访问value报错,且空输入时返回空字符串)。
五、可选链在方法调用中的应用(对应视频 11:16-13:20)
5.1 核心作用
检查方法是否存在后再调用,避免因调用 “非函数”(如undefined)而报错。
- 语法:
obj?.methodName(参数)(若obj.methodName不存在或非函数,返回undefined,不执行调用)
5.2 示例演示
基于restaurant对象,模拟方法存在 / 不存在的场景:
javascript
1 | const restaurant = { |
5.3 注意事项
-
可选链仅检查 “方法是否存在”,不检查 “方法是否可调用”(如
obj.method是普通变量而非函数时,仍会报错)。 -
示例:
javascript
1
2const restaurant = { order: "这是字符串,不是方法" };
// restaurant.order?.() 会报错:Uncaught TypeError: restaurant.order is not a function
六、可选链在数组中的应用(对应视频 13:21-16:04)
6.1 核心作用
检查数组元素是否存在,避免因访问 “越界索引” 或 “空数组” 的元素而报错。
- 语法:
- 访问指定索引:
arr?.[index](若arr为null/undefined,或index超出数组长度,返回undefined) - 访问嵌套元素:
arr?.[index]?.prop(数组元素为对象时,安全访问其属性)
- 访问指定索引:
6.2 示例演示
场景 1:数组非空且元素存在
javascript
1 | const users = [ |
场景 2:数组空或索引越界
javascript
1 | const emptyUsers = []; // 空数组 |
6.3 对比传统写法
传统方式需先检查数组是否存在且长度大于索引,代码如下:
javascript
1 | const getUserName = (arr, index) => { |
- 结论:可选链将条件判断简化为
arr?.[index]?.name ?? '默认值',代码更简洁。
七、总结与常见误区(对应视频 16:05-16:11)
7.1 核心知识点总结
| 应用场景 | 语法示例 | 核心作用 |
|---|---|---|
| 对象属性访问 | obj?.prop/obj?.prop1?.prop2 |
安全访问嵌套属性,空值返回undefined |
| 动态属性访问 | obj?.[dynamicProp] |
变量作为属性名时,避免属性不存在报错 |
| 方法调用 | obj?.method(参数) |
检查方法存在后调用,避免非函数调用报错 |
| 数组元素访问 | arr?.[index]/arr?.[i]?.prop |
安全访问数组元素,避免越界或空数组报错 |
| 配合默认值 | obj?.prop ?? '默认值' |
仅空值触发默认值,不影响0/''等假值 |
7.2 常见误区
- 误区 1:认为可选链可替代所有条件判断
- 错误:可选链仅处理 “空值”,若需判断 “值是否符合业务规则”(如
age > 18),仍需额外条件。 - 示例:
const isAdult = user?.age > 18 ?? false(若user.age为17,返回false,正确;若user为空,返回false,正确)。
- 错误:可选链仅处理 “空值”,若需判断 “值是否符合业务规则”(如
- 误区 2:过度使用可选链
- 错误:对确定存在的属性(如自己定义的本地对象)使用
?.,增加不必要的语法开销。 - 示例:
const name = user.name(user是本地定义的对象,确定有name属性,无需user?.name)。
- 错误:对确定存在的属性(如自己定义的本地对象)使用
- 误区 3:混淆
?.与&&- 区别:
&&会对所有 “假值” 返回左侧(如obj.prop = 0时,obj && obj.prop返回0,obj?.prop也返回0,效果一致);但?.更简洁,且支持多层嵌套(obj?.p1?.p2vsobj && obj.p1 && obj.p1.p2)。
- 区别:
7.3 最佳实践
- 接口数据处理:对后端返回的不确定字段(如
res.data?.list?.[0]?.id)必用可选链。 - DOM 操作:访问可能未渲染的元素(如
document.querySelector('.modal')?.style.display)必用可选链。 - 本地对象:确定存在的属性不用可选链,不确定的属性(如动态生成的对象)用可选链。


