## 14.布尔值
> 原文: [http://exploringjs.com/impatient-js/ch_booleans.html](http://exploringjs.com/impatient-js/ch_booleans.html)
>
> 贡献者:[飞龙](https://github.com/wizardforcel)
基本类型*布尔值*包含两个值 - `false`和`true`:
```js
> typeof false
'boolean'
> typeof true
'boolean'
```
### 14.1。转换为布尔值
这三种方法可以将任意值`x`转换为布尔值。
* `Boolean(x)`
最具描述性;推荐。
* `x ? true : false`
使用条件运算符([在本章后面解释](ch_booleans.html#conditional-operator))。
* `!!x`
使用[逻辑非运算符(`!`)](ch_booleans.html#logical-not)。此运算符将其操作数强制转换为布尔值。它被第二次应用来获得非否定的结果。
表 4 描述了各种值如何转换为布尔值。
表 4:将值转换为布尔值
| `x` | `Boolean(x)` |
| --- | --- |
| `undefined` | `false` |
| `null` | `false` |
| 布尔值 | `x`(无变化) |
| 数值 | `0 → false`,`NaN → false` |
| | 其他数字` → true` |
| 字符串值 | `'' → false` |
| | 其他字符串` → true` |
| 对象值 | 总是`true` |
### 14.2。真值和假值
在 JavaScript 中,如果您读取了不存在的内容(例如缺失参数或缺失属性),则通常会得到`undefined`。在这些情况下,存在性检查相当于将值与`undefined`进行比较。例如,以下代码检查对象`obj`是否具有属性`.prop`:
```js
if (obj.prop !== undefined) {
// obj has property .prop
}
```
为简化此检查,我们可以使用一个事实,`if`语句始终将其条件值转换为布尔值:
```js
if ('abc') { // true, if converted to boolean
console.log('Yes!');
}
```
因此,我们可以使用以下代码来检查`obj.prop`是否存在。这与`undefined`相比不太精确,但也更短:
```js
if (obj.prop) {
// obj has property .prop
}
```
这种简化的检查非常流行,引入了以下两个名称:
* 如果它在转换为布尔值时是`true`,则称为*真值*。
* 如果它在转换为布尔值时是`false`,则称为*假值*。
查询表 4,我们可以列出一个详尽的假值列表:
* `undefined`,`null`
* 布尔:`false`
* 数字:`0`,`NaN`
* 字符串:`''`
所有其他值(包括*所有*对象)都是真值:
```js
> Boolean('abc')
true
> Boolean([])
true
> Boolean({})
true
```
#### 14.2.1。陷阱:真实性检查是不精确的
真实性检查有一个陷阱:它们不是很精确。考虑前面的例子:
```js
if (obj.prop) {
// obj has property .prop
}
```
如果出现以下情况,则跳过`if`语句的正文:
* 缺少`obj.prop`(在这种情况下,JavaScript 返回`undefined`)。
但是,如果出现以下情况,也会跳过它:
* `obj.prop`是`undefined`。
* `obj.prop`是任何其他假值(`null`,`0`,`''`等)。
在实践中,这很少会引起问题,但你必须意识到这个陷阱。
#### 14.2.2。检查真实性或虚假性
```js
if (x) {
// x is truthy
}
if (!x) {
// x is falsy
}
if (x) {
// x is truthy
} else {
// x is falsy
}
const result = x ? 'truthy' : 'falsy';
```
最后一行中使用的条件运算符将在[本章后面的章节](ch_booleans.html#conditional-operator)中解释。
#### 14.2.3。用例:是否提供了参数?
真值检查通常用于确定函数的调用者是否提供了参数:
```js
function func(x) {
if (!x) {
throw new Error('Missing parameter x');
}
// ···
}
```
从好的方面来说,这种模式已经建立并且很短。它正确地为`undefined`和`null`抛出错误。
而另一面,有前面提到的陷阱:代码也会对所有其他假值抛出错误。
另一种方法是检查`undefined`:
```js
if (x === undefined) {
throw new Error('Missing parameter x');
}
```
#### 14.2.4。用例:存在属性吗?
真实性检查通常也用于确定属性是否存在:
```js
function readFile(fileDesc) {
if (!fileDesc.path) {
throw new Error('Missing property: .path');
}
// ···
}
readFile({ path: 'foo.txt' }); // no error
```
这种模式也已建立,并且有一个常见的警告:它不仅会在属性丢失时抛出,而且如果它存在并且具有任何假值。
如果你真的想检查属性是否存在,你必须使用[`in`运算符](ch_single-objects.html#in-operator):
```js
if (! ('path' in fileDesc)) {
throw new Error('Missing property: .path');
}
```
![](https://img.kancloud.cn/3e/d5/3ed5755d562179ae6c199264f5e21157.svg) **练习:真实性**
`exercises/booleans/truthiness_exrc.js`
### 14.3。条件运算符(`? :`)
条件运算符是`if`语句的表达式版本。它的语法是:
```js
«condition» ? «thenExpression» : «elseExpression»
```
求值如下:
* 如果`condition`是真值,求值并返回`thenExpression`。
* 否则,求值并返回`elseExpression`。
条件运算符也称为*三元运算符*,因为它有三个操作数。
例子:
```js
> true ? 'yes' : 'no'
'yes'
> false ? 'yes' : 'no'
'no'
> '' ? 'yes' : 'no'
'no'
```
下面的代码演示了,通过条件选择`then`和`else`两个分支中的任何一个 - 只求值该分支。另一个分支不是。
```js
const x = (true ? console.log('then') : console.log('else'));
// Output:
// 'then'
```
### 14.4。二元逻辑运算符:和(`x && y`),或(`x || y`)
运算符`&&`和`||`是*值保留*和*短路*的。那是什么意思?
*值保留*意味着操作数被解释为布尔值,但返回值不变:
```js
> 12 || 'hello'
12
> 0 || 'hello'
'hello'
```
*短路*表示:如果第一个操作数已经确定了结果,则不求值第二个操作数。延迟求值其操作数的唯一其他运算符是条件运算符:通常,在执行操作之前求值所有操作数。
例如,如果第一个操作数是假值,则逻辑和(`&&`)不会计算其第二个操作数:
```js
const x = false && console.log('hello');
// No output
```
如果第一个操作数是真值,则执行`console.log()`:
```js
const x = true && console.log('hello');
// Output:
// 'hello'
```
#### 14.4.1。逻辑和(`x && y`)
表达式`a && b`(“`a`和`b`”)的求值如下:
* 求值`a`。
* 结果是假值吗?把它返回。
* 否则,求值`b`并返回结果。
换句话说,以下两个表达式大致相同:
```js
a && b
!a ? a : b
```
例子:
```js
> false && true
false
> false && 'abc'
false
> true && false
false
> true && 'abc'
'abc'
> '' && 'abc'
''
```
#### 14.4.2。逻辑或(`||`)
表达式`a || b`(“`a`或`b`”)的求值如下:
* 求值`a`。
* 结果是真值?把它返回。
* 否则,求值`b`并返回结果。
换句话说,以下两个表达式大致相同:
```js
a || b
a ? a : b
```
例子:
```js
> true || false
true
> true || 'abc'
true
> false || true
true
> false || 'abc'
'abc'
> 'abc' || 'def'
'abc'
```
#### 14.4.3。通过逻辑或(`||`)的默认值
有时您会收到一个值,如果它不是`null`或`undefined`,则只想使用它。否则,您希望使用默认值作为后备。您可以通过`||`运算符执行此操作:
```js
const valueToUse = valueReceived || defaultValue;
```
以下代码显示了一个真实示例:
```js
function countMatches(regex, str) {
const matchResult = str.match(regex); // null or Array
return (matchResult || []).length;
}
```
如果`str`内有`regex`的一个或多个匹配项,则`.match()`返回一个数组。如果没有匹配,则很遗憾地返回`null`(而不是空数组)。我们通过`||`运算符来解决这个问题。
![](https://img.kancloud.cn/3e/d5/3ed5755d562179ae6c199264f5e21157.svg) **练习:通过或运算符(`||`)**的默认值
`exercises/booleans/default_via_or_exrc.js`
### 14.5。逻辑非(`!`)
表达式`!x`(“Not `x`”)的求值如下:
* 求值`x`。
* 这是真值?返回`false`。
* 否则,返回`true`。
例子:
```js
> !false
true
> !true
false
> !0
true
> !123
false
> !''
true
> !'abc'
false
```
![](https://img.kancloud.cn/ff/a8/ffa8e16628cad59b09c786b836722faa.svg) **测验**
参见[测验应用程序](ch_quizzes-exercises.html#quizzes)。
- I.背景
- 1.关于本书(ES2019 版)
- 2.常见问题:本书
- 3. JavaScript 的历史和演变
- 4.常见问题:JavaScript
- II.第一步
- 5.概览
- 6.语法
- 7.在控制台上打印信息(console.*)
- 8.断言 API
- 9.测验和练习入门
- III.变量和值
- 10.变量和赋值
- 11.值
- 12.运算符
- IV.原始值
- 13.非值undefined和null
- 14.布尔值
- 15.数字
- 16. Math
- 17. Unicode - 简要介绍(高级)
- 18.字符串
- 19.使用模板字面值和标记模板
- 20.符号
- V.控制流和数据流
- 21.控制流语句
- 22.异常处理
- 23.可调用值
- VI.模块化
- 24.模块
- 25.单个对象
- 26.原型链和类
- 七.集合
- 27.同步迭代
- 28.数组(Array)
- 29.类型化数组:处理二进制数据(高级)
- 30.映射(Map)
- 31. WeakMaps(WeakMap)
- 32.集(Set)
- 33. WeakSets(WeakSet)
- 34.解构
- 35.同步生成器(高级)
- 八.异步
- 36. JavaScript 中的异步编程
- 37.异步编程的 Promise
- 38.异步函数
- IX.更多标准库
- 39.正则表达式(RegExp)
- 40.日期(Date)
- 41.创建和解析 JSON(JSON)
- 42.其余章节在哪里?