JavaScript中雙問(wèn)號(hào)(??)操作符詳解
在 JavaScript 中,??
被稱為空值合并操作符(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 ?? "匿名用戶"; console.log(displayName); // 輸出:"匿名用戶"
在這個(gè)例子中,因?yàn)?username
是 undefined
,所以最終 displayName
賦值為右側(cè)的 “匿名用戶”。
如果 username
有一個(gè)實(shí)際的值,比如:
let username = "張三"; let displayName = username ?? "匿名用戶"; console.log(displayName); // 輸出:"張三"
那么就直接使用 username
的值,不使用默認(rèn)值。
二、為什么需要 ?? 操作符
1. 傳統(tǒng)的 || 存在的問(wèn)題
在 ??
出現(xiàn)之前,我們常常用邏輯或 ||
來(lái)處理默認(rèn)值,比如:
let username = ""; let displayName = username || "匿名用戶"; console.log(displayName); // 輸出:"匿名用戶"
問(wèn)題是,||
會(huì)把**所有假值(falsy value)**都當(dāng)成無(wú)效,包括:
false
0
NaN
""
(空字符串)null
undefined
上面例子中,雖然 username
是空字符串 ""
,理論上是有意義的(可能用戶就是想提交一個(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 ?? "匿名用戶"; 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)文章
微信小程序基于canvas漸變實(shí)現(xiàn)的彩虹效果示例
這篇文章主要介紹了微信小程序基于canvas漸變實(shí)現(xiàn)的彩虹效果,結(jié)合實(shí)例形式分析了微信小程序線性漸變及圓形漸變的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-05-05javascript實(shí)現(xiàn)全角半角檢測(cè)的方法
這篇文章主要介紹了javascript實(shí)現(xiàn)全角半角檢測(cè)的方法,涉及javascript針對(duì)字符遍歷與檢測(cè)的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07js閉包的6種應(yīng)用場(chǎng)景總結(jié)
如果一個(gè)函數(shù)訪問(wèn)了此函數(shù)的父級(jí)及父級(jí)以上的作用域變量,那么這個(gè)函數(shù)就是一個(gè)閉包,本文將給大家分享js閉包的6種應(yīng)用場(chǎng)景,文中有詳細(xì)的代碼示例,需要的朋友可以參考下2023-09-09詳解JavaScript如何利用異步解密回調(diào)地獄
為了更好地處理這些異步操作,JavaScript?引入了異步編程的概念,這篇文章主要來(lái)和大家詳細(xì)聊聊JavaScript中異步的相關(guān)應(yīng)用,希望對(duì)大家有所幫助2024-02-02JS簡(jiǎn)單判斷滾動(dòng)條的滾動(dòng)方向?qū)崿F(xiàn)方法
這篇文章主要介紹了JS簡(jiǎn)單判斷滾動(dòng)條的滾動(dòng)方向?qū)崿F(xiàn)方法,涉及javascript針對(duì)scrollTop事件的相關(guān)操作技巧,需要的朋友可以參考下2017-04-04JS實(shí)現(xiàn)仿QQ效果的三級(jí)豎向菜單
這篇文章主要介紹了JS實(shí)現(xiàn)仿QQ效果的三級(jí)豎向菜單,以實(shí)例形式分析了JavaScript遍歷頁(yè)面元素及動(dòng)態(tài)改變頁(yè)面css樣式的技巧,需要的朋友可以參考下2015-09-09js簡(jiǎn)單實(shí)現(xiàn)HTML標(biāo)簽Select聯(lián)動(dòng)帶跳轉(zhuǎn)
Select聯(lián)動(dòng)帶跳轉(zhuǎn)的效果想必大家并不陌生吧,下面有個(gè)不錯(cuò)的示例,感興趣的朋友可以參考下2013-10-10ibm官方資料把應(yīng)用程序從 Internet Explorer 遷移到 Mozilla
使特定于 Internet Explorer 的 Web 應(yīng)用程序在 Mozilla 上運(yùn)行時(shí),您遇到過(guò)麻煩嗎?本文討論了將應(yīng)用程序遷移到基于開(kāi)源 Mozilla 瀏覽器上時(shí)的常見(jiàn)問(wèn)題。首先討論跨瀏覽器開(kāi)發(fā)的基本技術(shù),然后介紹克服 Mozilla 和 Internet Explorer 之間差異的策略。2008-04-04兼容ie ff div 層 打開(kāi)+關(guān)閉+ 拖動(dòng)+遮罩+移動(dòng)+動(dòng)畫(huà)改變高寬
div層 打開(kāi)+關(guān)閉+ 拖動(dòng)+遮罩+移動(dòng)+動(dòng)畫(huà)改變高寬的實(shí)例js代碼2008-07-07