← 返回目录

16. 可选链 ?. / 逻辑赋值

可选链 ?. 和逻辑赋值 ??= / ||= / &&=。

核心两个:
?.——属性不存在不报错,直接返回 undefined
??=——只有 null/undefined 才赋值
||=——只有 falsy 才赋值

坑:?. 比 && 链更短、?? 和 || 区别(?? 只对 null/undefined)、可选链不能用来赋值

16.1 互动演示

点按钮看 ?. 和 ??= 的行为。

16.2 知识点讲解

一、可选链 ?.

① 层层判断 → ?. 直接往下找

以前读深层数据 config.db.host,得每一层都问一句"有没有",写一长串 &&?. 一放,自动帮你问。

// 一个套娃对象:config 里有 db,db 里有 host
let config = { db: { host: "localhost" } };

// 以前:每层都要 && 判断"这一层有没有"
// 一层层 && 问过去,空了就断
let host = config && config.db && config.db.host;

// ^^^^^^ ^^^^^^^^^^^^ ^^^^^^^^^^^^^^
// config有吗? db有吗? db.host 有吗?
// localhost
console.log(host);

// 现在:?. 一放,中间任何一环是空的就返回 undefined
// ?. 像防撞条:中间哪层空了就直接停,不报错
let host = config?.db?.host;

// ^^ ^^ 中间没有就停下,不报错
// localhost
console.log(host);

// undefined(x 不存在,但不报错!)
console.log(config?.x?.y);

?. 是"安全访问":链上任何一环是 null / undefined,就短路返回 undefined,继续往下读会直接报错。解析接口返回的深层数据(res.data.user.name)时最常用,不用写一长串 &&。

② 调方法也能用:obj.fn?.

不仅读属性,调方法也能加 ?.:方法不存在就不调,返回 undefined。

// 空对象,里面啥方法都没有
let obj = {};

// obj.fn?. —— fn 不存在就不调用,返回 undefined,不报错
// obj.fn —— fn 不存在会报错:fn is not a function

二、逻辑赋值:||= &&= ??=

③ 基本对比:先判断再赋值 → 一步到位

||= 是"左边是假值就换成右边",&&= 是"左边是真值就换成右边",??= 是"左边是 null/undefined 才换"。都是 a = a 运算 b 的简写。

// 以前
// 左边是假值
let a = false;

// 左边是假 → 赋 true
a = a || true;

// 现在
// 再来一遍
let a = false;

// 等价于 a = a || true
a ||= true;

④ 关键区别:||= 会误伤 0 和 "",??= 不会

|| 看的是"是不是假值"(0、""、false、NaN 都算假),?? 只看"是不是 null / undefined"。

// 0 是有效值
let n = 0;

// || 把 0 当假,换成 100
n ||= 100;

// 100(0 被当成"假",被换掉了!)
console.log(n);

// 0 是有效值
let m = 0;

// ?? 只认 null/undefined,0 不动
m ??= 100;

// 0(0 是有效值,保留)
console.log(m);

如果你用 ||= 给用户配置兜底,用户传了 0(表示"不限制")也会被悄悄换成默认值。这就是线上常见的隐性 bug——给默认值时优先用 ??=,它只在 null/undefined 时才动手。

16.3 实战:用在哪 / 常见坑 / 怎么解决

① 可能在什么地方用:读接口深层字段(res?.data?.user?.name)、调用可选方法(obj.fn?.)、组件 props 兜底(props.title ?? "默认")、给配置对象补默认值。

② 常见的问题:||= 误伤 0 和 "";把 ?. 写成 ? ? 中间有空格;对整个表达式误加 ?. 导致可读性差。

③ 解决思路:兜底一律用 ?? / ??=,别用 ||?. 紧跟属性名无空格;链式访问控制在 3 层以内,太深就先把中间变量取出来。

一句话:?. 安全往下找,??= 安全给默认值;取默认值别用 ||=,会误伤 0 和 ""。

本页重点

API作用参数返回值代码示例
?.链上任何一环是空值就直接停下对象?.属性值或 undefinedobj?.a?.b;
??只在左边是 null/undefined 时才取右边左, 右结果值a ?? b;
||=左边是假值就换成右边(会误伤 0)左, 右结果值a ||= 100;
??=只在左边是 null/undefined 时才赋值左, 右结果值a ?? b;