JavaScript中雙問號(??)操作符詳解
在 JavaScript 中,?? 被稱為空值合并操作符(Nullish Coalescing Operator)。這是 ES2020(ES11)引入的一項新特性,主要用于處理默認值的賦值問題。相比傳統(tǒng)的 || 邏輯或操作符,?? 在判斷標準上更加嚴格,能更準確地表達“僅在值為 null 或 undefined 時使用默認值”的意圖。本文將詳細介紹 ?? 的作用、用法、與其他操作符的區(qū)別及實際應用場景。
一、雙問號(??)操作符概述
1. 什么是空值合并操作符
空值合并操作符 ?? 是一種邏輯運算符,用于在左側表達式的值為 null 或 undefined 時,返回右側的默認值。簡單來說,就是:
- 如果左側的值是
null或undefined,返回右側的值; - 否則,返回左側的值。
2. 基本語法
let result = a ?? b;
a是要檢查的值;b是當a為null或undefined時使用的默認值;- 最終
result的值是a或b,取決于a是否為null或undefined。
3. 簡單示例
let username; let displayName = username ?? "匿名用戶"; console.log(displayName); // 輸出:"匿名用戶"
在這個例子中,因為 username 是 undefined,所以最終 displayName 賦值為右側的 “匿名用戶”。
如果 username 有一個實際的值,比如:
let username = "張三"; let displayName = username ?? "匿名用戶"; console.log(displayName); // 輸出:"張三"
那么就直接使用 username 的值,不使用默認值。
二、為什么需要 ?? 操作符
1. 傳統(tǒng)的 || 存在的問題
在 ?? 出現(xiàn)之前,我們常常用邏輯或 || 來處理默認值,比如:
let username = ""; let displayName = username || "匿名用戶"; console.log(displayName); // 輸出:"匿名用戶"
問題是,|| 會把**所有假值(falsy value)**都當成無效,包括:
false0NaN""(空字符串)nullundefined
上面例子中,雖然 username 是空字符串 "",理論上是有意義的(可能用戶就是想提交一個空的名字),但 || 認為空字符串是無效的,于是強行用了默認值。這并不是我們想要的。
2. ?? 更合理的默認值邏輯
?? 只在 null 和 undefined 時才使用默認值,其它的假值(比如 0、false、"")都會被當作有效值保留下來。
修改上面的例子:
let username = ""; let displayName = username ?? "匿名用戶"; console.log(displayName); // 輸出:""
這次不會強行替換默認值,而是保留了空字符串。這就更加符合實際開發(fā)中對于“值是否存在”的真實判斷需求。
三、?? 操作符的使用細節(jié)
1. null 和 undefined 的區(qū)別對待
?? 只關心 null 和 undefined,忽略其他 falsy 值。
示例:
console.log(false ?? "默認值"); // false
console.log(0 ?? 100); // 0
console.log("" ?? "默認字符串"); // ""
console.log(null ?? "默認值"); // "默認值"
console.log(undefined ?? "默認值"); // "默認值"
可以看到,只有當值為 null 或 undefined 時,右側的默認值才生效。
2. 與三元表達式(條件表達式)的對比
很多人可能習慣使用三元表達式:
let result = (a !== null && a !== undefined) ? a : b;
其實用 ?? 可以大大簡化:
let result = a ?? b;
這樣代碼更加簡潔,易讀性也更好。
3. 與邏輯運算符優(yōu)先級相關
?? 的優(yōu)先級比 || 和 && 要低,但比賦值 = 高。在組合使用時,需要注意加括號明確邏輯。
錯誤示例:
let a = null || undefined ?? "默認值"; // SyntaxError: Unexpected token '??'
正確寫法應該加括號:
let a = (null || undefined) ?? "默認值"; console.log(a); // 輸出:"默認值"
或者徹底拆開來寫,避免混用。
4. 禁止與 && 和 || 直接混用
JavaScript 規(guī)定,如果要同時使用 ?? 和 &&、||,必須用括號包裹清晰邏輯,否則會拋出 SyntaxError。
例如:
let x = (a || b) ?? c;
而不是:
let x = a || b ?? c; // ? 錯誤,語法錯誤
四、實際應用場景
1. 設置默認參數(shù)
函數(shù)參數(shù)如果沒有傳值,可以用 ?? 設置默認值。
function greet(name) {
let userName = name ?? "游客";
console.log(`你好,${userName}`);
}
greet("李雷"); // 你好,李雷
greet(); // 你好,游客
2. 讀取對象屬性
讀取對象中的某個屬性時,防止屬性不存在導致顯示錯誤。
let user = {
name: "小明",
age: 0
};
console.log(user.name ?? "匿名"); // 小明
console.log(user.age ?? "未知"); // 0
console.log(user.gender ?? "保密"); // 保密
這里即使 age 是 0,?? 也不會替換成默認值。
3. 配合解構賦值使用
在解構賦值時,結合 ?? 可以更加靈活處理默認值。
let settings = {
theme: null,
layout: "grid"
};
let theme = settings.theme ?? "light";
let layout = settings.layout ?? "list";
console.log(theme); // light
console.log(layout); // grid
如果 theme 是 null,則使用默認值 light;如果 layout 已經(jīng)有值 grid,則保留。
4. 配合可選鏈(?.)使用
?? 和可選鏈(?.)搭配使用非常高效,可以避免層層判斷。
let user = {
profile: {
nickname: ""
}
};
let nickname = user.profile?.nickname ?? "未命名";
console.log(nickname); // ""
這里即使 nickname 是空字符串,也不會被替換;如果 profile 不存在,也不會拋出異常,而是走默認值。
五、常見問題與注意事項
1. 區(qū)分 falsy 值和 null/undefined
?? 只針對 null 和 undefined,不像 || 那樣針對所有 falsy 值。這是它最核心的區(qū)別。務必根據(jù)業(yè)務場景選擇使用哪種操作符。
如果你希望 0、false、“” 也能觸發(fā)默認值,用 ||; 如果你只關心 null 或 undefined,應該用 ??。
2. 語法錯誤要注意加括號
混合使用 &&、|| 和 ?? 時,務必加括號明確優(yōu)先級,否則 JavaScript 會拋出語法錯誤。
3. 瀏覽器兼容性
??是 ES2020 新增的特性;- 現(xiàn)代瀏覽器(Chrome 80+,F(xiàn)irefox 72+,Edge 80+,Safari 13.1+)基本已經(jīng)支持;
- 如果需要兼容老舊瀏覽器(比如 IE11),可以使用 Babel 轉譯處理。
六、總結
空值合并操作符 ?? 是一個非常實用的 JavaScript 新特性,它可以幫助我們更加準確地處理默認值,避免傳統(tǒng) || 在 0、false、“” 等值上的邏輯誤判。掌握 ?? 的使用,不僅可以讓你的代碼更加簡潔,也能讓邏輯更加清晰明確。特別是在函數(shù)參數(shù)處理、對象屬性讀取、配置項設置等場景中,?? 都能發(fā)揮極大的作用。
在日常開發(fā)中,只要牢記:只有在值為 null 或 undefined 時,才使用默認值,你就能準確地應用好 ??,寫出更優(yōu)雅、更健壯的 JavaScript 代碼。
到此這篇關于JavaScript中雙問號(??)操作符詳解的文章就介紹到這了,更多相關JavaScript 雙問號內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JavaScript實現(xiàn)時間表動態(tài)效果
這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)時間表動態(tài)效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07
小程序云開發(fā)獲取不到數(shù)據(jù)庫記錄的解決方法
這篇文章主要為大家詳細介紹了小程序云開發(fā)獲取不到數(shù)據(jù)庫記錄的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-05-05
深入探討JavaScript異步編程中Promise的關鍵要點
這篇文章將全面深入地探討Promise,包括其前身、歷史、能力、優(yōu)點、缺點以及提供每個方法的案例,感興趣的小伙伴可以跟隨小編一學習一下2023-06-06
JS中for,for...in,for...of和forEach的區(qū)別和用法實例
JS遍歷數(shù)組(循環(huán)數(shù)組)的方式有多種,可以使用傳統(tǒng)的for循環(huán),也可以使用升級版的for in循環(huán),還可以使用Array類型的forEach() 方法,這篇文章主要給大家介紹了關于JS中for、for...in、for...of和forEach的區(qū)別和用法的相關資料,需要的朋友可以參考下2021-11-11

