JavaScript 中 ?? 和 || 操作符的区别
问题概述
在 JavaScript 中,当需要为变量提供默认值时,开发者经常需要在 ??
(空值合并操作符)和 ||
(逻辑或操作符)之间做出选择。虽然它们在某些情况下行为相同,但在处理 falsy 值(假值)时存在关键差异。
核心区别
关键区别
||
操作符:当左侧操作数为任何 falsy 值 时返回右侧操作数??
操作符:仅当左侧操作数为 null 或 undefined 时返回右侧操作数
JavaScript 中的 falsy 值包括:false
、0
、''
(空字符串)、null
、undefined
、NaN
。而 nullish 值仅指 null
和 undefined
。
代码示例对比
console.log(0 || "default") // "default"
console.log('' || "default") // "default"
console.log(false || "default") // "default"
console.log(null || "default") // "default"
console.log(undefined || "default")// "default"
console.log(0 ?? "default") // 0
console.log('' ?? "default") // ""
console.log(false ?? "default") // false
console.log(null ?? "default") // "default"
console.log(undefined ?? "default")// "default"
实际应用场景
场景一:表单处理
处理表单数据时,空字符串可能是有效输入,不应被默认值替换:
// 如果用户清空电话号码字段,会被替换为默认值
const phone = document.querySelector('#phone').value || '未知号码'
// 空字符串 '' 是 falsy,会返回 '未知号码'
// 只有 null 或 undefined 时才会使用默认值
const phone = document.querySelector('#phone').value ?? '未知号码'
// 空字符串 '' 会被保留
场景二:数值计算
处理可能为 0 的数值时:
function addYears(years) {
const yearsToAdd = years || 1 // 如果 years=0,会变成 1
return currentAge + yearsToAdd
}
addYears(0) // 不会保持 0 年增加
function addYears(years) {
const yearsToAdd = years ?? 1 // 只有 null/undefined 时使用默认值
return currentAge + yearsToAdd
}
addYears(0) // 正确保持 0 年增加
场景三:API 数据处理
从接口获取数据时,区分"未提供"和"空值":
// 从API获取用户数据
const userData = await fetchUserData()
// 如果API返回中缺少score字段或显式设置为null/undefined
const score = userData.score ?? 0 // 仅对nullish值使用默认值
// 如果score是空字符串或0,它们会被保留而不是被替换
何时使用哪个操作符
选择指南
- 使用
??
:当你只想排除null
和undefined
,但需要保留其他 falsy 值(如0
、false
、""
)时 - 使用
||
:当你需要排除所有 falsy 值,包括0
、""
、false
、null
、undefined
时
兼容性说明
??
操作符是 ES2020 中引入的现代 JavaScript 特性:
- Node.js 14+ 原生支持
- TypeScript 3.7+ 支持
- 旧版环境需要通过 Babel 等工具进行转译
总结对比表
| 场景 | ||
结果 | ??
结果 | 推荐选择 | |------|-----------|-----------|----------| | null \| undefined
| 使用默认值 | 使用默认值 | 两者相同 | | 0
| 使用默认值 | 保留 0
| ?? | | ""
(空字符串) | 使用默认值 | 保留 ""
| ?? | | false
| 使用默认值 | 保留 false
| ?? | | 其他 truthy 值 | 保留原值 | 保留原值 | 两者相同 |
在实际开发中,大多数情况下推荐使用 ??
操作符,因为它能更精确地处理各种边界情况,避免意外的类型转换。只有当明确需要排除所有 falsy 值时,才使用 ||
操作符。