今天我们来聊一个JavaScript里非常实用的语法:空值合并运算符 。它的写法是两个问号:??。
这个东西有什么用呢?简单说,它帮你处理那些"可能有值,也可能是null或undefined"的情况。
?? 运算符怎么用
空值合并运算符的用法很简单:
ini
let result = 左侧值 ?? 右侧值;
它的规则是:
• 如果左侧值 不是null也不是undefined,就返回左侧值
• 如果左侧值 是null或undefined,就返回右侧值
用这个运算符重写上面的例子:
ini
let user = {
name: null
};
let displayName = user.name ?? "游客";
console.log(displayName); // 输出:游客
一行代码就搞定了!是不是很简洁?
和 || 运算符的区别
你可能用过||(逻辑或)运算符来设置默认值:
ini
let value = someValue || "默认值";
||和??很像,但有一个重要区别:
• || 会在左侧值为 假值 时返回右侧值 • ?? 只在左侧值为 null或undefined 时返回右侧值
JavaScript中的假值包括:
• false
• 0
• ""(空字符串)
• null
• undefined
• NaN
看一个对比例子:
ini
let count = 0;
let price = "";
// 使用 ||
let result1 = count || 10; // 输出:10(0是假值)
let result2 = price || "未知"; // 输出:"未知"(空字符串是假值)
// 使用 ??
let result3 = count ?? 10; // 输出:0(0不是null或undefined)
let result4 = price ?? "未知"; // 输出:""(空字符串不是null或undefined)
在实际开发中,如果你希望0、false、""这些值被保留,就用??。如果你希望所有假值都用默认值替换,就用||。
实际场景
场景1:函数参数默认值
javascript
function greet(name) {
// 如果没传name,或者传了null/undefined,就用"朋友"
let finalName = name ?? "朋友";
console.log(`你好,${finalName}!`);
}
greet("张三"); // 输出:你好,张三!
greet(null); // 输出:你好,朋友!
greet(); // 输出:你好,朋友!
场景2:配置对象合并
javascript
// 用户设置
let userSettings = {
theme: null, // 用户没选主题
fontSize: 14
};
// 默认设置
let defaultSettings = {
theme: "light",
fontSize: 16,
language: "zh-CN"
};
// 合并设置:优先用用户的,用户没设置就用默认的
let finalSettings = {
theme: userSettings.theme ?? defaultSettings.theme,
fontSize: userSettings.fontSize ?? defaultSettings.fontSize,
language: userSettings.language ?? defaultSettings.language
};
console.log(finalSettings);
// 输出:{ theme: "light", fontSize: 14, language: "zh-CN" }
场景3:链式调用
ini
let user = {
profile: {
address: {
city: "北京"
}
}
};
// 安全地获取嵌套属性
let city = user?.profile?.address?.city ?? "未知城市";
console.log(city); // 输出:北京
// 如果中间某个属性不存在
let user2 = {
profile: null
};
let city2 = user2?.profile?.address?.city ?? "未知城市";
console.log(city2); // 输出:未知城市
这里用到了可选链操作符?.,它和??配合使用非常方便。
注意事项
1. 不能直接和&&或||一起用
ini
// 这样写会报错
let x = a && b ?? c; // SyntaxError
// 需要加括号
let x = (a && b) ?? c; // 正确
let y = a && (b ?? c); // 正确
2. 优先级问题
??的优先级比=高,但比大多数运算符低。为了代码清晰,建议在复杂表达式中使用括号。
ini
// 这样写可能不是你想要的
let result = a ?? b && c;
// 加括号更清晰
let result = a ?? (b && c);
3. 在旧版本浏览器中可能不支持
??是ES2020引入的语法。如果你需要支持旧浏览器,可能需要使用Babel等工具进行转换。
什么时候用??
记住这个简单的判断标准:
• 当你只想在变量是null或undefined时才用默认值,用??
• 当你想在所有假值(false、0、""等)情况下都用默认值,用||
在实际项目中,??通常更适合处理配置、用户输入、API响应等场景,因为这些场景中0、false、""往往是有效值,不应该被默认值替换。