在 ECMAScript 2021(ES12)中,JavaScript 引入了新的邏輯賦值運算子 &&=
和 ??=
。這些運算子將邏輯運算子與賦值運算子相結合,提供了更加簡潔、直觀的賦值方式。
雖然已經進入標準比較久了,但是我在實際開發中見到的還比較少,今天我們一起來學習下。
邏輯與賦值運算子 &&=
&&=
的工作原理
&&=
運算子是邏輯與運算子(&&
)和賦值運算子(=
)的結合。它的作用是:僅當左側變數為真值(truthy)時,才將右側的值賦給左側變數。傳統的寫法需要使用 if
語句或邏輯運算子,&&=
則提供了更為簡潔的方式。
傳統寫法對比:
// 使用 if 語句
if (x) {
x = y;
}
// 使用邏輯與運算子
x = x && y;
// 使用 `&&=` 運算子(ES2021)
x &&= y;
真值和假值的概念
在 JavaScript 中,以下值被認為是假值(falsy):
false
0
''
(空字串)null
undefined
NaN
其他所有值都被視為真值(truthy)。
示例解析
示例 1:使用者登入狀態
let isLoggedIn = true;
isLoggedIn &&= getUserData(); // 如果已經登入,獲取使用者資料
function getUserData() {
return { name: 'ConardLi', age: 17 };
}
// 結果:isLoggedIn 變為 { name: 'ConardLi', age: 17 }
示例 2:庫存更新
let stock = 17;
function sell(quantity) {
stock >= quantity &&= stock - quantity;
}
sell(5); // stock 為 5
sell(17); // stock 保持為 5,因為 5 >= 17 為 false
在上述示例中,sell
函式僅在庫存足夠時才減少庫存,防止出現負庫存的情況。
應用場景
(1)條件更新屬性
let config = {
debugMode: true,
logLevel: null
};
// 僅當 debugMode 為真時,設定 logLevel
config.debugMode &&= (config.logLevel = 'verbose');
// 結果:config.logLevel 為 'verbose'
(2)鏈式判斷
let user = {
isActive: true,
hasMembership: true
};
// 僅當使用者活躍且有會員資格時,給予折扣
user.isActive &&= user.hasMembership &&= applyDiscount();
function applyDiscount() {
return '已應用折扣';
}
// 結果:user.hasMembership 變為 '已應用折扣'
空值合併賦值運算子 ??=
??=
的工作原理
??=
運算子結合了空值合併運算子(??
)和賦值運算子(=
)。它的作用是:僅當左側變數為 null
或 undefined
時,才將右側的值賦給左側變數。這有助於在變數未被初始化時提供預設值。
傳統寫法對比:
// 使用 if 語句
if (options.timeout === null || options.timeout === undefined) {
options.timeout = 3000;
}
// 使用空值合併運算子
options.timeout = options.timeout ?? 3000;
// 使用 `??=` 運算子(ES2021)
options.timeout ??= 3000;
與其他賦值方式的比較
問題:
- 邏輯或
||
: 會將0
、''
、false
等合法值視為需要賦預設值的情況,可能導致意外的結果。
let delay = 0;
delay = delay || 1000; // delay 被誤賦值為 1000
解決方案:
??=
: 僅在變數為null
或undefined
時才賦值,避免了上述問題。
let delay = 0;
delay ??= 1000; // delay 保持為 0
使用三元運算子:
user.name = (user.name !== null && user.name !== undefined) ? user.name : 'Anonymous';
問題: 程式碼較為冗長,可讀性不高。
使用 ??=
:
user.name ??= 'Anonymous';
優勢: 簡潔明瞭,僅在變數為 null
或 undefined
時才賦值,不影響其他假值。
應用場景
??=
運算子非常適合為可能未定義的變數設定預設值,且不會干擾有效的假值。
示例:
let score = 0;
score ??= 100; // 保持為 0
let tag = '';
tag ??= 'default'; // 保持為 ''
let active = false;
active ??= true; // 保持為 false
配置預設引數:
function initializeSettings(settings) {
settings.theme ??= 'light';
settings.notificationsEnabled ??= true;
settings.autoSaveInterval ??= 300;
return settings;
}
最後
JavaScript 的 &&=
和 ??=
運算子為我們提供了更為簡潔和精確的賦值方式:
&&=
運算子: 僅在左側變數為真值時才進行賦值,適合用於需要在保持假值的同時,根據真值條件更新變數的場景。??=
運算子: 僅在左側變數為null
或undefined
時才進行賦值,適合用於為未定義或空值變數設定預設值的場景。