為什麼 JavaScript 的 || 和 && 不只是布林運算?——從「短路求值」談起
更新日期: 2025 年 4 月 21 日
在多數程式語言中,邏輯運算子(如 ||
、&&
)的用途是用來處理「條件判斷」,它們的最終結果通常是布林值 true
或 false
:
if (a > 0 && b > 0) {
// 條件為真才執行
}
然而在 JavaScript 中,||
和 &&
有一個更靈活且強大的設計——它們不一定只回傳布林值,這背後的關鍵就在於:「短路求值(short-circuit evaluation)」。
什麼是短路求值?為何這樣設計?
短路求值(Short-circuit evaluation)是什麼?
短路求值是一種在邏輯運算中常見的效能優化技巧。
它的核心思想是:
當運算途中已經能決定結果,就不再繼續計算剩下的部分。
換句話說,整個邏輯表達式「不一定要全部算完」,只要途中某一個條件足以判斷整體結果,就可以直接停下來。
這不只是一種偷懶的寫法,而是源自於電腦科學中的效率設計原則。
💡 舉個生活例子
假設你早上起床,會根據兩個條件決定要不要帶傘:
- 今天會下雨?
- 帶不帶傘?
如果第一個條件就已經是「不會下雨」,你根本就不需要去判斷第二個條件,因為「帶不帶傘」這件事已經有答案了。
這就是短路求值的邏輯思維:遇到足夠資訊,後面就不浪費力氣。
為什麼叫做「Short-circuit」?
這個詞源自於電子電路的運作邏輯。
在電路設計中,「circuit」指的是電流流動的路徑,而「short-circuit(短路)」則是當電流發現一條更快、更短、更直接的路徑可以走,就會避開原本完整的路線,從而提早結束整個迴路。
這種「繞過冗長流程、直接產出結果」的思想,被借用來形容程式語言中邏輯運算的這種提早中斷行為。
在程式中,「短路」不是壞事,而是一種節省計算資源的好事。
JavaScript 中的短路行為:不只邏輯,更是值的選擇機制
在 JavaScript 中,邏輯運算子 ||
(邏輯或)與 &&
(邏輯與)不只是判斷條件是否為 true
或 false
,它們還會根據運算過程中的「第一個足以決定結果的值」直接回傳該值本身。
這種設計,讓 JavaScript 的邏輯運算子具有高度的彈性與表現力,能夠兼顧條件控制與資料處理。
||
(邏輯或 OR)
🔹 邏輯意義:
只要「其中一個」為真,整體就為真。
🔹 短路邏輯:
當左側的值為 truthy(可視為「成立」的值),就會直接回傳該值,不再理會右邊的運算。
🔹 回傳行為:
- 若左邊為 truthy ➜ 回傳左邊的值
- 否則 ➜ 回傳右邊的值(不管是否為 truthy)
🔍 範例:
console.log("A" || "B"); // "A":左邊已經成立,不需看右邊
console.log("" || "B"); // "B":左邊是 falsy,回傳右邊
console.log(null || 0 || "Hello"); // "Hello":前兩個都 falsy,回傳第三個
這個行為常被用來提供預設值或防止空值錯誤。
✅ 補充:falsy 值
在 JavaScript 中,被判定為 false 的值稱為 falsy 值。這些值在布林上下文中,會被自動轉換為布林值 false。常見的 falsy 值包括:
NaN – 表示非數字值(Not-a-Number)
false – 布林值 false
0 – 數字零
-0 – 負零
0n – BigInt 的零,這是一種能夠表示非常大整數的數據類型
” ” 或 ‘ ‘ 或 “ “ – 空的字符串值(不管是使用雙引號、單引號還是反引號)
null – 表示無值
undefined – 表示未定義的值
&&
(邏輯與 AND)
🔹 邏輯意義:
只有「兩者都為真」,整體才為真。
🔹 短路邏輯:
當左側的值為 falsy(可視為「不成立」的值),就會直接回傳該值,不再執行右邊。
🔹 回傳行為:
- 若左邊為 falsy ➜ 回傳左邊的值
- 否則 ➜ 回傳右邊的值
🔍 範例:
console.log("A" && "B"); // "B":左邊為真,繼續運算並回傳右邊
console.log("" && "B"); // "":左邊為假,短路回傳左邊
console.log(1 && 0 && "C"); // 0:第一個 truthy,第二個 falsy,短路
這個行為常被用來做條件執行或防止不必要的操作。
短路求值的實用應用:讓程式更簡潔與安全
預設值處理(使用 ||
)
當一個變數可能為 null
、undefined
或空值時,我們可以用 ||
提供一個「退路」:
const username = inputName || "訪客";
這等於說:
- 若
inputName
是有效的(truthy) ➜ 使用它 - 否則 ➜ 回傳
"訪客"
當作替代值
✅ 用途:用於表單、設定值、顯示畫面等場景,是處理空值的最佳寫法。
條件執行(使用 &&
)
&&
可以拿來讓某段程式碼「只有在符合條件時才執行」,取代傳統 if
寫法。
isLoggedIn && showDashboard();
這等於:
- 若
isLoggedIn
為真 ➜ 執行showDashboard()
- 若為假 ➜ 整段不執行,無錯誤也無副作用
✅ 用途:執行函式、渲染畫面、觸發副作用時,能簡化條件邏輯。
補充觀念:什麼是「退路(Fallback)」?
在程式語言中,「退路」是一種預備方案。當主要路線失效或不可用時,就切換到備用值或備用行為。
短路求值就是這種「退路設計」最經典的語法手段。
🔍 範例:
const lang = userSetting.lang || "en";
// 若 userSetting.lang 沒有被設定 ➜ 自動退回英文版
這種設計有三大優點:
- 簡潔:不需多餘的
if
或三元運算子
- 容錯:避免 null 或 undefined 導致程式錯誤
- 彈性:便於快速切換預設行為
短路求值 + 優先順序:決定「誰先算」與「何時停」
前面我們了解了 ||
和 &&
各自的短路行為,但在實際應用中,兩者往往混合出現於同一個表達式中。
這時候,就需要了解另一個關鍵概念:運算子的優先順序(Operator Precedence)。
優先順序是什麼?
當一個表達式中有多個運算子時,JavaScript 必須決定哪個運算子要先被執行。
就像數學中「先乘除後加減」,JavaScript 也有屬於自己的優先順序。
✅ &&
優先於 ||
在 JavaScript 中,邏輯運算子的優先順序如下(數字越高,優先級越高):
運算子 | 名稱 | 優先順序 | 結合性 |
---|---|---|---|
! | 邏輯非 | 17 | 右至左(right-to-left) |
&& | 邏輯與 | 6 | 左至右(left-to-right) |
|| | 邏輯或 | 5 | 左至右(left-to-right) |
因此當 &&
和 ||
同時出現在一個表達式中時,會先執行 &&
,再執行 ||
。
優先順序 + 短路求值 的結合流程
這兩個機制搭配時,運作順序會是:
1️⃣ 先依據優先順序確定計算順序
2️⃣ 每個子運算依照短路規則進行,提早停止不必要的計算
🧪 範例解析
const result = '' && 'World' || 'Goodbye';
🔹 依照優先順序,先算 '' && 'World'
''
是 falsy → 直接回傳''
,不算右邊'World'
(短路)
🔹 接著變成:'' || 'Goodbye'
''
是 falsy → 回傳'Goodbye'
✅ 最終結果為: "Goodbye"
🧪 再看一個混合例子:
const result = 'Hi' || 0 && 'Bye';
🔹 依照優先順序,先算 0 && 'Bye'
0
是 falsy → 短路回傳0
🔹 接著變成:'Hi' || 0
'Hi'
是 truthy → 回傳'Hi'
✅ 結果是: "Hi"
小技巧:不確定就加括號
在條件邏輯比較複雜、含有多個邏輯運算子時,加上括號可以幫助你:
- 清楚控制運算順序
- 提高可讀性
- 避免誤會與 bug
// 不推薦(容易搞錯)
const result = user && isActive || isGuest;
// 推薦(邏輯明確)
const result = (user && isActive) || isGuest;
✅ 小結:兩個機制如何分工合作?
機制 | 角色 | 重點行為 |
---|---|---|
運算子優先順序 | 誰先被處理 | && 優先於 ` |
短路求值 | 要不要處理右邊 | &&:左邊為假就不繼續;` |
如果說優先順序是誰先上場,那麼短路求值就是誰先下班。
這兩個觀念一起掌握,你就能完全理解 JavaScript 中邏輯運算的真實行為!