給急躁的程式設計師的 JavaScript(ES2022 版)
請支持這本書:購買捐款
(廣告,請不要阻擋。)

15 布林值



基本類型布林值包含兩個值 – falsetrue

> typeof false
'boolean'
> typeof true
'boolean'

15.1 轉換為布林值

  “轉換為 [類型]” 的含義

“轉換為 [類型]” 是“將任意值轉換為 [類型] 類型的值”的簡稱。

以下三種方式可以將任意值 x 轉換為布林值。

表 4 說明了如何將各種值轉換為布林值。

表 4:將值轉換為布林值。
x Boolean(x)
undefined false
null false
布林值 x(不變)
數字 0 falseNaN false
其他數字 true
bigint 0 false
其他數字 true
字串 '' false
其他字串 true
符號 true
物件 永遠是 true

15.2 假值和真值

在檢查 if 敘述、while 迴圈或 do-while 迴圈的條件時,JavaScript 的運作方式可能與你的預期不同。舉例來說,以下條件

if (value) {}

在許多程式語言中,這個條件等於

if (value === true) {}

然而,在 JavaScript 中,它等於

if (Boolean(value) === true) {}

也就是說,JavaScript 會檢查將 value 轉換為布林值時是否為 true。這種檢查非常常見,因此引入了以下名稱

每個值都是真值或假值。查閱表 4,我們可以列出所有假值的清單

所有其他值(包括所有物件)都是真值

> Boolean('abc')
true
> Boolean([])
true
> Boolean({})
true

15.2.1 檢查真值或假值

if (x) {
  // x is truthy
}

if (!x) {
  // x is falsy
}

if (x) {
  // x is truthy
} else {
  // x is falsy
}

const result = x ? 'truthy' : 'falsy';

最後一行中使用的條件運算子,將在 本章節後面說明

  練習:真值

exercises/booleans/truthiness_exrc.mjs

15.3 基於真值的判斷是否存在

在 JavaScript 中,如果你讀取不存在的東西(例如,遺失的參數或遺失的屬性),通常會得到 undefined 作為結果。在這些情況下,判斷是否存在等於將值與 undefined 進行比較。例如,以下程式碼檢查物件 obj 是否有屬性 .prop

if (obj.prop !== undefined) {
  // obj has property .prop
}

由於 undefined 為假值,我們可以將此檢查縮短為

if (obj.prop) {
  // obj has property .prop
}

15.3.1 陷阱:基於真值的判斷是否存在並不精確

基於真值的判斷是否存在有一個陷阱:它們並不精確。考慮前面這個範例

if (obj.prop) {
  // obj has property .prop
}

如果下列情況發生,則會跳過 if 敘述的主體

然而,如果下列情況發生,也會跳過

在實務上,這很少造成問題,但你必須知道這個陷阱。

15.3.2 使用案例:是否提供了參數?

真值檢查通常用於判斷函數呼叫者是否提供了參數

function func(x) {
  if (!x) {
    throw new Error('Missing parameter x');
  }
  // ···
}

好處是,這個模式已建立且簡短。它會正確地對 undefinednull 擲回錯誤。

壞處是,有前面提到的陷阱:此程式碼也會對所有其他假值擲回錯誤。

替代方法是檢查 undefined

if (x === undefined) {
  throw new Error('Missing parameter x');
}

15.3.3 使用案例:屬性是否存在?

真值檢查也常被用於判斷屬性是否存在

function readFile(fileDesc) {
  if (!fileDesc.path) {
    throw new Error('Missing property: .path');
  }
  // ···
}
readFile({ path: 'foo.txt' }); // no error

這個模式也已建立,並具有通常的警告:它不僅在屬性遺失時擲回錯誤,也發生在屬性存在且具有任何假值時。

如果你真的想檢查屬性是否存在,你必須使用 in 運算子

if (! ('path' in fileDesc)) {
  throw new Error('Missing property: .path');
}

15.4 條件運算子 (? :)

條件運算子是 if 敘述的表達式版本。它的語法是

«condition» ? «thenExpression» : «elseExpression»

它會以如下方式評估

條件運算子也稱為 三元運算子,因為它有三個運算元。

範例

> true ? 'yes' : 'no'
'yes'
> false ? 'yes' : 'no'
'no'
> '' ? 'yes' : 'no'
'no'

以下程式碼示範了無論透過條件選擇哪個分支「then」和「else」,只會評估那個分支。另一個分支不會。

const x = (true ? console.log('then') : console.log('else'));

// Output:
// 'then'

15.5 二元邏輯運算子:And (x && y)、Or (x || y)

二元邏輯運算子 &&||值保留短路

15.5.1 值保留

值保留 表示運算元被解釋為布林值,但未變更地傳回

> 12 || 'hello'
12
> 0 || 'hello'
'hello'

15.5.2 短路

短路 表示如果第一個運算元已決定結果,則不會評估第二個運算元。唯一其他會延遲評估其運算元的運算子是條件運算子。通常,所有運算元都會在執行運算之前評估。

例如,邏輯 And (&&) 如果第一個運算元為假值,就不會評估其第二個運算元

const x = false && console.log('hello');
// No output

如果第一個運算元為真值,則會執行 console.log()

const x = true && console.log('hello');

// Output:
// 'hello'

15.5.3 邏輯 And (x && y)

表達式 a && b(「a And b」)會以如下方式評估

  1. 評估 a
  2. 結果為假值嗎?回傳它。
  3. 否則,評估 b 並回傳結果。

換句話說,以下兩個表達式大致相等

a && b
!a ? a : b

範例

> false && true
false
> false && 'abc'
false

> true && false
false
> true && 'abc'
'abc'

> '' && 'abc'
''

15.5.4 邏輯或 (||)

表達式 a || b(「ab」)評估如下

  1. 評估 a
  2. 結果為真值嗎?回傳它。
  3. 否則,評估 b 並回傳結果。

換句話說,以下兩個表達式大致相等

a || b
a ? a : b

範例

> true || false
true
> true || 'abc'
true

> false || true
true
> false || 'abc'
'abc'

> 'abc' || 'def'
'abc'
15.5.4.1 邏輯或 (||) 的傳統用例:提供預設值

ECMAScript 2020 引入了空值合併運算子 (??) 來提供預設值。在此之前,邏輯或用於此目的

const valueToUse = receivedValue || defaultValue;

請參閱 §14.4「空值合併運算子 (??) 用於預設值 [ES2020]」 以取得更多關於 ??|| 在此情況下的缺點的資訊。

  傳統練習:透過或運算子 (||) 提供預設值

exercises/booleans/default_via_or_exrc.mjs

15.6 邏輯非 (!)

表達式 !x(「非 x」)評估如下

  1. 評估 x
  2. 它是真值嗎?回傳 false
  3. 否則,回傳 true

範例

> !false
true
> !true
false

> !0
true
> !123
false

> !''
true
> !'abc'
false

  測驗

請參閱 測驗應用程式