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