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

