JavaScript 支援一系列 複合賦值運算子,讓程式設計師能夠簡潔地表達二元運算與賦值。目前僅支援數學或位元運算。
一直以來缺少的是將邏輯運算與賦值結合在一起的能力。現在有了!JavaScript 現在支援邏輯賦值,使用新的運算子 &&=
、||=
和 ??=
。
邏輯賦值運算子 #
在深入探討新的運算子之前,讓我們複習一下現有的複合賦值運算子。例如,lhs += rhs
的意義大致等同於 lhs = lhs + rhs
。這種大致的等價性適用於所有現有的運算子 @=
,其中 @
代表二元運算子,例如 +
或 |
。值得注意的是,嚴格來說,這僅在 lhs
是變數時才正確。對於較複雜的左邊運算式,例如 obj[computedPropertyName()] += rhs
,左邊運算式只會評估一次。
現在讓我們深入探討新的運算子。與現有的運算子不同,當 @
是邏輯運算時,lhs @= rhs
並不大致等於 lhs = lhs @ rhs
:&&
、||
或 ??
。
// As an additional review, here is the semantics of logical and:
x && y
// → y when x is truthy
// → x when x is not truthy
// First, logical and assignment. The two lines following this
// comment block are equivalent.
// Note that like existing compound assignment operators, more complex
// left-hand sides are only evaluated once.
x &&= y;
x && (x = y);
// The semantics of logical or:
x || y
// → x when x is truthy
// → y when x is not truthy
// Similarly, logical or assignment:
x ||= y;
x || (x = y);
// The semantics of nullish coalescing operator:
x ?? y
// → y when x is nullish (null or undefined)
// → x when x is not nullish
// Finally, nullish coalescing assignment:
x ??= y;
x ?? (x = y);
短路語意 #
與數學和位元對應項不同,邏輯賦值遵循其各自邏輯運算的短路行為。它們只會在邏輯運算會評估右邊運算式時執行賦值。
起初這可能令人困惑。為什麼不像其他複合賦值那樣無條件地賦值給左邊運算式?
差異背後有一個實用的理由。將邏輯運算與賦值結合時,賦值可能會造成副作用,而此副作用應根據邏輯運算的結果有條件地發生。無條件地造成副作用可能會對程式效能甚至正確性產生負面影響。
讓我們用一個函式的兩個版本來具體說明,此函式會在元素中設定預設訊息。
// Display a default message if it doesn’t override anything.
// Only assigns to innerHTML if it’s empty. Doesn’t cause inner
// elements of msgElement to lose focus.
function setDefaultMessage() {
msgElement.innerHTML ||= '<p>No messages<p>';
}
// Display a default message if it doesn’t override anything.
// Buggy! May cause inner elements of msgElement to
// lose focus every time it’s called.
function setDefaultMessageBuggy() {
msgElement.innerHTML = msgElement.innerHTML || '<p>No messages<p>';
}
注意:由於 innerHTML
屬性 已指定 回傳空字串,而非 null
或 undefined
,因此必須使用 ||=
而非 ??=
。撰寫程式碼時,請記住許多 Web API 都不會使用 null
或 undefined
來表示為空或不存在。
在 HTML 中,將值賦予元素的 .innerHTML
屬性具有破壞性。內部子項會被刪除,並從新賦予的字串中解析新的子項並插入。即使新字串與舊字串相同,它也會造成額外的作業,並導致內部元素失去焦點。由於這個不造成不需要的副作用的實用原因,邏輯賦值運算子的語意會短路賦值。
思考與其他複合賦值運算子的對稱性可能會有幫助,如下所示。數學和位元運算子是無條件的,因此賦值也是無條件的。邏輯運算子是有條件的,因此賦值也是有條件的。
邏輯賦值支援 #
- Chrome: 自版本 85 起支援
- Firefox: 自版本 79 起支援
- Safari: 自版本 14 起支援
- Node.js: 自版本 16 起支援
- Babel: 支援