# 布爾運算符
## 概述
布爾運算符用于將表達式轉為布爾值,一共包含四個運算符。
- 取反運算符:`!`
- 且運算符:`&&`
- 或運算符:`||`
- 三元運算符:`?:`
## 取反運算符(!)
取反運算符是一個感嘆號,用于將布爾值變為相反值,即`true`變成`false`,`false`變成`true`。
```javascript
!true // false
!false // true
```
對于非布爾值,取反運算符會將其轉為布爾值。可以這樣記憶,以下六個值取反后為`true`,其他值都為`false`。
- `undefined`
- `null`
- `false`
- `0`
- `NaN`
- 空字符串(`''`)
```javascript
!undefined // true
!null // true
!0 // true
!NaN // true
!"" // true
!54 // false
!'hello' // false
![] // false
!{} // false
```
上面代碼中,不管什么類型的值,經過取反運算后,都變成了布爾值。
如果對一個值連續做兩次取反運算,等于將其轉為對應的布爾值,與`Boolean`函數的作用相同。這是一種常用的類型轉換的寫法。
```javascript
!!x
// 等同于
Boolean(x)
```
上面代碼中,不管`x`是什么類型的值,經過兩次取反運算后,變成了與`Boolean`函數結果相同的布爾值。所以,兩次取反就是將一個值轉為布爾值的簡便寫法。
## 且運算符(&&)
且運算符(`&&`)往往用于多個表達式的求值。
它的運算規則是:如果第一個運算子的布爾值為`true`,則返回第二個運算子的值(注意是值,不是布爾值);如果第一個運算子的布爾值為`false`,則直接返回第一個運算子的值,且不再對第二個運算子求值。
```javascript
't' && '' // ""
't' && 'f' // "f"
't' && (1 + 2) // 3
'' && 'f' // ""
'' && '' // ""
var x = 1;
(1 - 1) && ( x += 1) // 0
x // 1
```
上面代碼的最后一個例子,由于且運算符的第一個運算子的布爾值為`false`,則直接返回它的值`0`,而不再對第二個運算子求值,所以變量`x`的值沒變。
這種跳過第二個運算子的機制,被稱為“短路”。有些程序員喜歡用它取代`if`結構,比如下面是一段`if`結構的代碼,就可以用且運算符改寫。
```javascript
if (i) {
doSomething();
}
// 等價于
i && doSomething();
```
上面代碼的兩種寫法是等價的,但是后一種不容易看出目的,也不容易除錯,建議謹慎使用。
且運算符可以多個連用,這時返回第一個布爾值為`false`的表達式的值。如果所有表達式的布爾值都為`true`,則返回最后一個表達式的值。
```javascript
true && 'foo' && '' && 4 && 'foo' && true
// ''
1 && 2 && 3
// 3
```
上面代碼中,例一里面,第一個布爾值為`false`的表達式為第三個表達式,所以得到一個空字符串。例二里面,所有表達式的布爾值都是`true`,所以返回最后一個表達式的值`3`。
## 或運算符(||)
或運算符(`||`)也用于多個表達式的求值。它的運算規則是:如果第一個運算子的布爾值為`true`,則返回第一個運算子的值,且不再對第二個運算子求值;如果第一個運算子的布爾值為`false`,則返回第二個運算子的值。
```javascript
't' || '' // "t"
't' || 'f' // "t"
'' || 'f' // "f"
'' || '' // ""
```
短路規則對這個運算符也適用。
```javascript
var x = 1;
true || (x = 2) // true
x // 1
```
上面代碼中,或運算符的第一個運算子為`true`,所以直接返回`true`,不再運行第二個運算子。所以,`x`的值沒有改變。這種只通過第一個表達式的值,控制是否運行第二個表達式的機制,就稱為“短路”(short-cut)。
或運算符可以多個連用,這時返回第一個布爾值為`true`的表達式的值。如果所有表達式都為`false`,則返回最后一個表達式的值。
```javascript
false || 0 || '' || 4 || 'foo' || true
// 4
false || 0 || ''
// ''
```
上面代碼中,例一里面,第一個布爾值為`true`的表達式是第四個表達式,所以得到數值4。例二里面,所有表達式的布爾值都為`false`,所以返回最后一個表達式的值。
或運算符常用于為一個變量設置默認值。
```javascript
function saveText(text) {
text = text || '';
// ...
}
// 或者寫成
saveText(this.text || '')
```
上面代碼表示,如果函數調用時,沒有提供參數,則該參數默認設置為空字符串。
## 三元條件運算符(?:)
三元條件運算符由問號(?)和冒號(:)組成,分隔三個表達式。它是 JavaScript 語言唯一一個需要三個運算子的運算符。如果第一個表達式的布爾值為`true`,則返回第二個表達式的值,否則返回第三個表達式的值。
```javascript
't' ? 'hello' : 'world' // "hello"
0 ? 'hello' : 'world' // "world"
```
上面代碼的`t`和`0`的布爾值分別為`true`和`false`,所以分別返回第二個和第三個表達式的值。
通常來說,三元條件表達式與`if...else`語句具有同樣表達效果,前者可以表達的,后者也能表達。但是兩者具有一個重大差別,`if...else`是語句,沒有返回值;三元條件表達式是表達式,具有返回值。所以,在需要返回值的場合,只能使用三元條件表達式,而不能使用`if..else`。
```javascript
console.log(true ? 'T' : 'F');
```
上面代碼中,`console.log`方法的參數必須是一個表達式,這時就只能使用三元條件表達式。如果要用`if...else`語句,就必須改變整個代碼寫法了。
- 前言
- 入門篇
- 導論
- 歷史
- 基本語法
- 數據類型
- 概述
- null,undefined 和布爾值
- 數值
- 字符串
- 對象
- 函數
- 數組
- 運算符
- 算術運算符
- 比較運算符
- 布爾運算符
- 二進制位運算符
- 其他運算符,運算順序
- 語法專題
- 數據類型的轉換
- 錯誤處理機制
- 編程風格
- console 對象與控制臺
- 標準庫
- Object 對象
- 屬性描述對象
- Array 對象
- 包裝對象
- Boolean 對象
- Number 對象
- String 對象
- Math 對象
- Date 對象
- RegExp 對象
- JSON 對象
- 面向對象編程
- 實例對象與 new 命令
- this 關鍵字
- 對象的繼承
- Object 對象的相關方法
- 嚴格模式
- 異步操作
- 概述
- 定時器
- Promise 對象
- DOM
- 概述
- Node 接口
- NodeList 接口,HTMLCollection 接口
- ParentNode 接口,ChildNode 接口
- Document 節點
- Element 節點
- 屬性的操作
- Text 節點和 DocumentFragment 節點
- CSS 操作
- Mutation Observer API
- 事件
- EventTarget 接口
- 事件模型
- Event 對象
- 鼠標事件
- 鍵盤事件
- 進度事件
- 表單事件
- 觸摸事件
- 拖拉事件
- 其他常見事件
- GlobalEventHandlers 接口
- 瀏覽器模型
- 瀏覽器模型概述
- window 對象
- Navigator 對象,Screen 對象
- Cookie
- XMLHttpRequest 對象
- 同源限制
- CORS 通信
- Storage 接口
- History 對象
- Location 對象,URL 對象,URLSearchParams 對象
- ArrayBuffer 對象,Blob 對象
- File 對象,FileList 對象,FileReader 對象
- 表單,FormData 對象
- IndexedDB API
- Web Worker
- 附錄:網頁元素接口
- a
- img
- form
- input
- button
- option
- video,audio