在 JavaScript 中,!!、?? 和 || 是三种常用于处理值的真假性或默认值 的操作符,但它们的行为和用途完全不同。下面逐一解释,并对比区别。
1. !! ------ 强制转为布尔值(Boolean)
作用:
将任意值显式转换为布尔类型 (true 或 false)。
原理:
- 第一个
!:将值转为布尔并取反; - 第二个
!:再取反一次,得到原始值的布尔等价值。
示例:
js
编辑
console.log(!!"hello"); // true
console.log(!!""); // false
console.log(!!0); // false
console.log(!!42); // true
console.log(!!null); // false
console.log(!!undefined); // false
console.log(!!{}); // true(对象总是 truthy)
常见用途:
-
显式获取某个值的"是否存在"状态:
js
编辑
const hasEmail = !!user.email; // 确保返回 true/false
2. || ------ 逻辑 OR(短路求值)
作用:
返回第一个 truthy 值;如果所有值都是 falsy,则返回最后一个。
✅ 注意 :它判断的是 falsy / truthy (不是
null/undefined专属)。
Falsy 值包括:
js
编辑
false, 0, -0, 0n, "", null, undefined, NaN
示例:
js
编辑
console.log("a" || "b"); // "a"("a" 是 truthy)
console.log("" || "default"); // "default"
console.log(0 || "number"); // "number"
console.log(null || "ok"); // "ok"
console.log(undefined || "hi"); // "hi"
// 常用于设置默认值(⚠️ 有陷阱!)
function greet(name) {
name = name || "Guest"; // 如果 name 是 falsy(如 ""、0),也会被替换!
console.log("Hello, " + name);
}
greet(""); // 输出: Hello, Guest ❌(可能不是你想要的)
⚠️ 问题 :
||会把0、""、false等合法值误判为"无效"。
3. ?? ------ 空值合并操作符(Nullish Coalescing)
作用:
仅当左侧值为 null 或 undefined 时,才返回右侧默认值。
✅ 只对
null/undefined敏感 ,其他 falsy 值(如0,"",false)会被保留。
示例:
js
编辑
console.log("a" ?? "b"); // "a"
console.log("" ?? "default"); // ""(空字符串被保留!)
console.log(0 ?? "number"); // 0(数字 0 被保留!)
console.log(false ?? "bool"); // false
console.log(null ?? "ok"); // "ok"
console.log(undefined ?? "hi"); // "hi"
正确设置默认值:
js
编辑
function greet(name) {
name = name ?? "Guest"; // 只有 name 为 null/undefined 时才用默认值
console.log("Hello, " + name);
}
greet(""); // 输出: Hello, ✅(空字符串被接受)
greet(null); // 输出: Hello, Guest
🔁 对比总结
| 表达式 | 判断条件 | 返回值示例 |
|---|---|---|
| `a | b` | |
a ?? b |
如果 a 是 null 或 undefined |
返回 b |
!!a |
将 a 转为 布尔值 |
true 或 false |
场景选择建议:
| 需求 | 推荐操作符 |
|---|---|
| "只要不是 null/undefined 就用原值" | ✅ ?? |
| "只要是 falsy(包括空字符串、0)就用默认值" | ` |
| "判断某个值是否存在(转布尔)" | ✅ !! |
💡 实际应用示例
js
编辑
const config = {
timeout: 0,
retries: null,
name: ""
};
// 错误:timeout 会被设为 5000(因为 0 是 falsy)
const timeout1 = config.timeout || 5000; // 5000 ❌
// 正确:只在 timeout 为 null/undefined 时设默认值
const timeout2 = config.timeout ?? 5000; // 0 ✅
// 判断用户是否设置了名字(即使为空字符串也算"设置了")
const hasName = !!config.name; // true(因为 "" 存在,只是空)
✅ 总结口诀:
!!x→ "x 是真还是假?"a || b→ "a 有没有值?没有就用 b" (把0、""当"没有")a ?? b→ "a 是 null/undefined 吗?是就用 b"(更精准的默认值)
📌 现代 JS 开发中,优先使用
??设置默认值,避免||的陷阱!
支持情况:?? 自 ES2020 起支持,所有现代浏览器和 Node.js 14+ 均可用。