W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
最近新增的特性這是一個(gè)最近添加到 JavaScript 的特性。 舊式瀏覽器可能需要 polyfills.
空值合并運(yùn)算符(nullish coalescing operator)的寫法為兩個(gè)問號(hào) ??
。
由于它對(duì)待 null
和 undefined
的方式類似,所以在本文中我們將使用一個(gè)特殊的術(shù)語對(duì)其進(jìn)行表示。為簡(jiǎn)潔起見,當(dāng)一個(gè)值既不是 null
也不是 undefined
時(shí),我們將其稱為“已定義的(defined)”。
a ?? b
的結(jié)果是:
a
?是已定義的,則結(jié)果為 ?a
?,a
?不是已定義的,則結(jié)果為 ?b
?。換句話說,如果第一個(gè)參數(shù)不是 null/undefined
,則 ??
返回第一個(gè)參數(shù)。否則,返回第二個(gè)參數(shù)。
空值合并運(yùn)算符并不是什么全新的東西。它只是一種獲得兩者中的第一個(gè)“已定義的”值的不錯(cuò)的語法。
我們可以使用我們已知的運(yùn)算符重寫 result = a ?? b
,像這樣:
result = (a !== null && a !== undefined) ? a : b;
現(xiàn)在你應(yīng)該清楚了 ??
的作用。讓我們來看看它的使用場(chǎng)景吧。
??
的常見使用場(chǎng)景是提供默認(rèn)值。
例如,在這里,如果 user
的值不為 null/undefined
則顯示 user
,否則顯示 匿名
:
let user;
alert(user ?? "匿名"); // 匿名(user 未定義)
在下面這個(gè)例子中,我們將一個(gè)名字賦值給了 user
:
let user = "John";
alert(user ?? "匿名"); // John(user 已定義)
我們還可以使用 ??
序列從一系列的值中選擇出第一個(gè)非 null/undefined
的值。
假設(shè)我們?cè)谧兞?nbsp;firstName
、lastName
或 nickName
中存儲(chǔ)著一個(gè)用戶的數(shù)據(jù)。如果用戶決定不填寫相應(yīng)的值,則所有這些變量的值都可能是未定義的。
我們想使用這些變量之一顯示用戶名,如果這些變量的值都是 null/undefined
,則顯示 “匿名”。
讓我們使用 ??
運(yùn)算符來實(shí)現(xiàn)這一需求:
let firstName = null;
let lastName = null;
let nickName = "Supercoder";
// 顯示第一個(gè)已定義的值:
alert(firstName ?? lastName ?? nickName ?? "匿名"); // Supercoder
或運(yùn)算符 ||
可以以與 ??
運(yùn)算符相同的方式使用。像我們?cè)?nbsp;上一章 所講的那樣。
例如,在上面的代碼中,我們可以用 ||
替換掉 ??
,也可以獲得相同的結(jié)果:
let firstName = null;
let lastName = null;
let nickName = "Supercoder";
// 顯示第一個(gè)真值:
alert(firstName || lastName || nickName || "Anonymous"); // Supercoder
縱觀 JavaScript 發(fā)展史,或 ||
運(yùn)算符先于 ??
出現(xiàn)。它自 JavaScript 誕生就存在了,因此開發(fā)者長(zhǎng)期將其用于這種目的。
另一方面,空值合并運(yùn)算符 ??
是最近才被添加到 JavaScript 中的,它的出現(xiàn)是因?yàn)槿藗儗?duì) ||
不太滿意。
它們之間重要的區(qū)別是:
||
? 返回第一個(gè) 真 值。??
? 返回第一個(gè) 已定義的 值。換句話說,||
無法區(qū)分 false
、0
、空字符串 ""
和 null/undefined
。它們都一樣 —— 假值(falsy values)。如果其中任何一個(gè)是 ||
的第一個(gè)參數(shù),那么我們將得到第二個(gè)參數(shù)作為結(jié)果。
不過在實(shí)際中,我們可能只想在變量的值為 null/undefined
時(shí)使用默認(rèn)值。也就是說,當(dāng)該值確實(shí)未知或未被設(shè)置時(shí)。
例如,考慮下面這種情況:
let height = 0;
alert(height || 100); // 100
alert(height ?? 100); // 0
height || 100
? 首先會(huì)檢查 ?height
? 是否為一個(gè)假值,它是 ?0
?,確實(shí)是假值。
||
? 運(yùn)算的結(jié)果為第二個(gè)參數(shù),?100
?。height ?? 100
? 首先會(huì)檢查 ?height
?是否為 ?null/undefined
?,發(fā)現(xiàn)它不是。
height
?的原始值,?0
?。實(shí)際上,高度 0
通常是一個(gè)有效值,它不應(yīng)該被替換為默認(rèn)值。所以 ??
運(yùn)算得到的是正確的結(jié)果。
??
運(yùn)算符的優(yōu)先級(jí)與 ||
相同,它們的的優(yōu)先級(jí)都為 4
,詳見:MDN。
這意味著,就像 ||
一樣,空值合并運(yùn)算符在 =
和 ?
運(yùn)算前計(jì)算,但在大多數(shù)其他運(yùn)算(例如 +
和 *
)之后計(jì)算。
所以我們可能需要在這樣的表達(dá)式中添加括號(hào):
let height = null;
let width = null;
// 重要:使用括號(hào)
let area = (height ?? 100) * (width ?? 50);
alert(area); // 5000
否則,如果我們省略了括號(hào),則由于 *
的優(yōu)先級(jí)比 ??
高,它會(huì)先執(zhí)行,進(jìn)而導(dǎo)致錯(cuò)誤的結(jié)果。
// 沒有括號(hào)
let area = height ?? 100 * width ?? 50;
// ……將這樣計(jì)算(不符合我們的期望):
let area = height ?? (100 * width) ?? 50;
出于安全原因,JavaScript 禁止將 ??
運(yùn)算符與 &&
和 ||
運(yùn)算符一起使用,除非使用括號(hào)明確指定了優(yōu)先級(jí)。
下面的代碼會(huì)觸發(fā)一個(gè)語法錯(cuò)誤:
let x = 1 && 2 ?? 3; // Syntax error
這個(gè)限制無疑是值得商榷的,它被添加到語言規(guī)范中是為了避免人們從 ||
切換到 ??
時(shí)的編程錯(cuò)誤。
可以明確地使用括號(hào)來解決這個(gè)問題:
let x = (1 && 2) ?? 3; // 正常工作了
alert(x); // 2
??
提供了一種從列表中選擇第一個(gè)“已定義的”值的簡(jiǎn)便方式。它被用于為變量分配默認(rèn)值:
// 當(dāng) height 的值為 null 或 undefined 時(shí),將 height 的值設(shè)置為 100
height = height ?? 100;
??
? 運(yùn)算符的優(yōu)先級(jí)非常低,僅略高于 ??
? 和 ?=
?,因此在表達(dá)式中使用它時(shí)請(qǐng)考慮添加括號(hào)。||
? 或 ?&&
? 一起使用。Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: