可选链(?.)与空值合并(??)
减少层层判断,提高可读性与健壮性。
javascript
const user = { profile: { name: "Elara" } };
console.log(user.profile?.name); // 'Elara'
console.log(user.stats?.level); // undefined(不抛错)
const val = 0 ?? 42; // 仅当左侧为 null/undefined 时取右侧
console.log(val); // 0(不同于 ||)
1
2
3
4
5
6
2
3
4
5
6
典型用法:
- 访问可能不存在的深层属性;
- 提供“空值”默认而非“假值”默认。
三种可选链形式
- 属性访问:
obj?.prop
- 索引访问:
arr?.[i]
- 函数/方法调用:
fn?.(args)
或obj.method?.(args)
javascript
user?.profile?.avatarUrl;
const first = list?.[0];
callback?.("hello"); // callback 存在且为函数时才调用
1
2
3
2
3
与空值合并(??)组合
??
只在左侧为 null 或 undefined 时才使用右侧默认值:
javascript
const title = post.title ?? "Untitled";
const page = (query.page ?? 1) + 0; // 0/空字符串不会被当作空值
1
2
2
对比 ||
(会把 0、''、false 当作“假值”而回退):
javascript
0 || 42; // 42(可能不是你要的)
0 ?? 42; // 0(保留有效的 0)
"" || "N/A"; // 'N/A'
"" ?? "N/A"; // ''
1
2
3
4
2
3
4
与逻辑赋值(&&=、||=、??=)
javascript
let a = 0;
let b = null;
let c = "x";
a ||= 42; // 0 被视为假 -> a=42(若不想这样请用 ??=)
b ??= 7; // 仅 null/undefined 时赋值 -> b=7
c &&= c + "!"; // 真值才更新 -> 'x!'
1
2
3
4
5
6
7
2
3
4
5
6
7
常见陷阱
- 可选链仅短路为 undefined,不会捕获错误;
- 不要在赋值左侧使用可选链(
obj?.prop = x
是语法错误); - 注意可选调用与方法丢失 this 的问题:
javascript
const obj = {
x: 1,
getX() {
return this.x;
},
};
const fn = obj.getX;
console.log(fn?.()); // undefined,因为 this 丢失
console.log(obj.getX?.()); // 1
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
最佳实践
- 当你确信“0/''/false 是有效值”时,优先
??
而非||
; - 深层访问前先用可选链缩短保护代码:
data?.a?.b?.c
; - 对可选的回调使用
cb?.()
代替显式判断; - 与类型系统(TS)搭配,减少非空断言的需要。
练习
- 写一个函数
safeGet(obj, pathArray, defaultValue)
,使用可选链与空值合并安全读取深层属性。 - 将使用
||
的默认值逻辑改为??
,以保留 0/''/false 等有效值。 - 为一个可选回调
onDone
改写为onDone?.(result)
,并比较可读性。