## 13.非值`undefined`和`null`
> 原文: [http://exploringjs.com/impatient-js/ch_undefined-null.html](http://exploringjs.com/impatient-js/ch_undefined-null.html)
>
> 贡献者:[飞龙](https://github.com/wizardforcel)
许多编程语言都有一个名为`null`的“非值”。它表示变量当前未指向对象。例如,尚未初始化时。
相比之下,JavaScript 有两个:`undefined`和`null`。
### 13.1。 `undefined`与`null`
两个值都非常相似,并且通常可互换使用。因此它们的区别是微妙的。语言本身具有以下区别:
* `undefined`表示“未初始化”(例如变量)或“不存在”(例如对象的属性)。
* `null`表示“故意没有任何对象值”([参考语言规范](https://tc39.github.io/ecma262/#sec-null-value))。
程序员可以做出以下区分:
* `undefined`是语言使用的非值(当某些内容未初始化时)。
* `null`表示“明确关闭”。也就是说,它有助于实现一种类型,既包含有意义的值又包含代表“无意义的值”的元值。这种类型在函数式编程中称为[*可选类型*或*可能类型*](https://en.wikipedia.org/wiki/Option_type) 。
### 13.2。 `undefined`和`null`的位置
以下小节描述了`undefined`和`null`在语言中的位置。我们将遇到几种机制,本书稍后将对此进行更详细的解释。
#### 13.2.1。 `undefined`的位置
未初始化的变量`myVar`:
```js
let myVar;
assert.equal(myVar, undefined);
```
未提供的参数`x`:
```js
function func(x) {
return x;
}
assert.equal(func(), undefined);
```
缺失属性`.unknownProp`:
```js
const obj = {};
assert.equal(obj.unknownProp, undefined);
```
如果没有通过`return`运算符显式指定函数的结果,JavaScript 会为您返回`undefined`:
```js
function func() {}
assert.equal(func(), undefined);
```
#### 13.2.2。 `null`的位置
对象的原型是一个对象,或者在原型链的末尾,是`null`。 `Object.prototype`没有原型:
```js
> Object.getPrototypeOf(Object.prototype)
null
```
如果将正则表达式(例如`/a/`)与字符串(例如`'x'`)匹配,则可以获得具有匹配数据的对象(如果匹配成功)或`null`(如果匹配失败):
```js
> /a/.exec('x')
null
```
[JSON 数据格式](ch_json.html)不支持`undefined`,仅支持`null`:
```js
> JSON.stringify({a: undefined, b: null})
'{"b":null}'
```
### 13.3。检查`undefined`或`null`
检查:
`x`有值吗?
```js
if (x === null) ···
if (x === undefined) ···
```
`x`是`undefined`还是`null`?
```js
if (x !== undefined && x !== null) {
// ···
}
if (x) { // truthy?
// x is neither: undefined, null, false, 0, NaN, ''
}
```
*真值*的意思是“如果强制转换为布尔值则为`true`”。*假值*的意思是“如果强制转换为布尔值则为`false`”。在[布尔值](ch_booleans.html#falsiness-truthiness)的章节中正确解释了这两个概念。
### 13.4。 `undefined`和`null`没有属性
`undefined`和`null`是两个唯一的 JavaScript 值,如果您尝试读取属性,则会获得异常。为了探索这种现象,让我们使用以下函数,它读取(“获取”)属性`.foo`并返回结果。
```js
function getFoo(x) {
return x.foo;
}
```
如果我们将`getFoo()`应用于各种值,我们可以看到它只对`undefined`和`null`失败:
```js
> getFoo(undefined)
TypeError: Cannot read property 'foo' of undefined
> getFoo(null)
TypeError: Cannot read property 'foo' of null
> getFoo(true)
undefined
> getFoo({})
undefined
```
### 13.5。 `undefined`和`null`的历史
在 Java(它激发了 JavaScript 的许多方面)中,初始化值取决于变量的静态类型:
* 具有对象类型的变量用`null`初始化。
* 每个原始类型都有自己的初始化值。例如,`int`变量用`0`初始化。
在 JavaScript 中,每个变量都可以包含对象值和原始值。因此,如果`null`表示“不是对象”,JavaScript 还需要一个初始化值,这意味着“既不是对象也不是原始值”。初始化值为`undefined`。
![](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.其余章节在哪里?