??的核心价值是精准区分“值未提供(null/undefined)”与“值已提供但为合法假值(0/''/false等)”,仅对null和undefined触发默认值,其余均原样返回。

空值合并运算符 ?? 的核心价值,就是帮你把“值确实没传(null 或 undefined)”和“值传了但恰好是 0、false、"" 这类合法假值”彻底分开。它不靠真假判断,只认两个空值。
明确识别哪些值算“真实无效”
?? 只对 null 和 undefined 响应,其余一切值——无论多“假”——都视为有效存在:
-
0 ?? 100→0(0是有效数值,不触发默认) -
false ?? true→false(布尔值已定义,不替换) -
"" ?? "default"→""(空字符串是合法字符串值) -
NaN ?? 0→NaN(不是null或undefined,原样返回) -
null ?? "fallback"→"fallback"(真正缺失,用默认) -
undefined ?? 42→42(未初始化或未传参,补上)
典型场景:配置项中保留语义化零值
比如接口返回分页参数:{ itemsPerPage: 0, enabled: false, theme: "" }。
- 用
||:config.itemsPerPage || 10→ 得到10(错误!0表示“每页显示 0 条”,不是没设) - 用
??:config.itemsPerPage ?? 10→ 得到0(正确保留业务含义) - 同理:
config.enabled ?? true保留false(明确禁用),config.theme ?? "light"保留空字符串(表示用主题名为空的方案)
与逻辑或(||)对比的关键动作
别再凭感觉选运算符,记住这个判断动作:
- 问自己:“如果这里是
0或false,我是否希望它被覆盖?” → 如果答案是否定的,必须用?? - 问自己:“我只关心这个值有没有被真正提供(不是
null/undefined)?” → 这正是??的设计目的 - 警惕
||的隐式布尔转换:它会把0当成“关”,把""当成“无”,而现实里它们常代表明确状态
实用写法建议
让意图清晰,避免歧义:
- 对对象属性取值时加括号:
(obj?.count) ?? 0(先可选链防报错,再 ?? 补默认) - 避免混用:
a ?? b || c会报语法错误;如需组合,显式加括号:(a ?? b) || c或a ?? (b || c) - 类型提示友好:TypeScript 中
value ?? defaultValue的推导结果更精确,不会把0或false从联合类型里意外剔除

















