# 布尔运算符
## 概述
布尔运算符用于将表达式转为布尔值,一共包含四个运算符。
- 取反运算符:`!`
- 且运算符:`&&`
- 或运算符:`||`
- 三元运算符:`?:`
## 取反运算符(!)
取反运算符是一个感叹号,用于将布尔值变为相反值,即`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