# null, undefined 和布爾值
## null 和 undefined
### 概述
`null`與`undefined`都可以表示“沒有”,含義非常相似。將一個變量賦值為`undefined`或`null`,老實說,語法效果幾乎沒區別。
```javascript
var a = undefined;
// 或者
var a = null;
```
上面代碼中,變量`a`分別被賦值為`undefined`和`null`,這兩種寫法的效果幾乎等價。
在`if`語句中,它們都會被自動轉為`false`,相等運算符(`==`)甚至直接報告兩者相等。
```javascript
if (!undefined) {
console.log('undefined is false');
}
// undefined is false
if (!null) {
console.log('null is false');
}
// null is false
undefined == null
// true
```
從上面代碼可見,兩者的行為是何等相似!谷歌公司開發的 JavaScript 語言的替代品 Dart 語言,就明確規定只有`null`,沒有`undefined`!
既然含義與用法都差不多,為什么要同時設置兩個這樣的值,這不是無端增加復雜度,令初學者困擾嗎?這與歷史原因有關。
1995年 JavaScript 誕生時,最初像 Java 一樣,只設置了`null`表示"無"。根據 C 語言的傳統,`null`可以自動轉為`0`。
```javascript
Number(null) // 0
5 + null // 5
```
上面代碼中,`null`轉為數字時,自動變成0。
但是,JavaScript 的設計者 Brendan Eich,覺得這樣做還不夠。首先,第一版的 JavaScript 里面,`null`就像在 Java 里一樣,被當成一個對象,Brendan Eich 覺得表示“無”的值最好不是對象。其次,那時的 JavaScript 不包括錯誤處理機制,Brendan Eich 覺得,如果`null`自動轉為0,很不容易發現錯誤。
因此,他又設計了一個`undefined`。區別是這樣的:`null`是一個表示“空”的對象,轉為數值時為`0`;`undefined`是一個表示"此處無定義"的原始值,轉為數值時為`NaN`。
```javascript
Number(undefined) // NaN
5 + undefined // NaN
```
### 用法和含義
對于`null`和`undefined`,大致可以像下面這樣理解。
`null`表示空值,即該處的值現在為空。調用函數時,某個參數未設置任何值,這時就可以傳入`null`,表示該參數為空。比如,某個函數接受引擎拋出的錯誤作為參數,如果運行過程中未出錯,那么這個參數就會傳入`null`,表示未發生錯誤。
`undefined`表示“未定義”,下面是返回`undefined`的典型場景。
```javascript
// 變量聲明了,但沒有賦值
var i;
i // undefined
// 調用函數時,應該提供的參數沒有提供,該參數等于 undefined
function f(x) {
return x;
}
f() // undefined
// 對象沒有賦值的屬性
var o = new Object();
o.p // undefined
// 函數沒有返回值時,默認返回 undefined
function f() {}
f() // undefined
```
## 布爾值
布爾值代表“真”和“假”兩個狀態。“真”用關鍵字`true`表示,“假”用關鍵字`false`表示。布爾值只有這兩個值。
下列運算符會返回布爾值:
- 前置邏輯運算符: `!` (Not)
- 相等運算符:`===`,`!==`,`==`,`!=`
- 比較運算符:`>`,`>=`,`<`,`<=`
如果 JavaScript 預期某個位置應該是布爾值,會將該位置上現有的值自動轉為布爾值。轉換規則是除了下面六個值被轉為`false`,其他值都視為`true`。
- `undefined`
- `null`
- `false`
- `0`
- `NaN`
- `""`或`''`(空字符串)
布爾值往往用于程序流程的控制,請看一個例子。
```javascript
if ('') {
console.log('true');
}
// 沒有任何輸出
```
上面代碼中,`if`命令后面的判斷條件,預期應該是一個布爾值,所以 JavaScript 自動將空字符串,轉為布爾值`false`,導致程序不會進入代碼塊,所以沒有任何輸出。
注意,空數組(`[]`)和空對象(`{}`)對應的布爾值,都是`true`。
```javascript
if ([]) {
console.log('true');
}
// true
if ({}) {
console.log('true');
}
// true
```
更多關于數據類型轉換的介紹,參見《數據類型轉換》一章。
## 參考鏈接
- Axel Rauschmayer, [Categorizing values in JavaScript](http://www.2ality.com/2013/01/categorizing-values.html)
- 前言
- 入門篇
- 導論
- 歷史
- 基本語法
- 數據類型
- 概述
- 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