一、基本資料型別
在介紹undefined與null之前,我們先來了解一下ECMAScript中的資料型別。在ECMAScript中有六種簡單資料型別(也稱為基本資料型別): Undefined、Null、Boolean、Number 和 String、Symbol (ES6中引入) 。還有一種複雜資料型別——Object。
Undefined和Null都只有一個值,分別對應著undefined和null。這兩種不同型別的值,既有著不同的語義和場景,又表現出較為相似的行為。
二、undefined
undefined 的字面意思就是:未定義的值 。這個值的語義是,希望表示一個變數最原始的狀態,而非人為操作的結果 。 這種原始狀態會在以下 4 種場景中出現:
1、宣告一個變數,但是沒有賦值
var foo;
console.log(foo); // undefined
複製程式碼
訪問 foo,返回了 undefined,表示這個變數自從宣告瞭以後,就從來沒有使用過,也沒有定義過任何有效的值。
2、訪問物件上不存在的屬性或者未定義的變數
console.log(Object.foo); // undefined
console.log(typeof demo); // undefined
複製程式碼
訪問 Object 物件上的 foo 屬性,返回 undefined , 表示Object 上不存在或者沒有定義名為 foo 的屬性;對未宣告的變數執行typeof操作符返回了undefined值。
3、函式定義了形參,但沒有傳遞實參
//函式定義了形參 a
function fn(a) {
console.log(a); // undefined
}
fn(); //未傳遞實參
複製程式碼
函式 fn 定義了形參 a,但 fn 被呼叫時沒有傳遞引數,因此,fn 執行時的引數 a 就是一個原始的、未被賦值的變數。
4、使用void對錶達式求值
void 0 ; // undefined
void false; // undefined
void []; // undefined
void null; // undefined
void function fn(){} ; // undefined
複製程式碼
ECMAScript 明確規定 void 操作符 對任何表示式求值都返回 undefined ,這和函式執行操作後沒有返回值的作用是一樣的,JavaScript 中的函式都有返回值,當沒有 return 操作時,就預設返回一個原始的狀態值,這個值就是 undefined,表明函式的返回值未被定義。
因此,undefined 一般都來自於某個表示式最原始的狀態值,不是人為操作的結果。當然,你也可以手動給一個變數賦值 undefined,但這樣做沒有意義,因為一個變數不賦值就是 undefined 。
三、null
null 的字面意思是:空值 。這個值的語義是,希望表示一個物件被人為的重置為空物件,而非一個變數最原始的狀態 。 在記憶體裡的表示就是,棧中的變數沒有指向堆中的記憶體物件。
1、一般在以下兩種情況下我們會將變數賦值為null
-
如果定義的變數在將來用於儲存物件,那麼最好將該變數初始化為null,而不是其他值。換句話說,只要意在儲存物件的變數還沒有真正儲存物件,就應該明確地讓該變數儲存null值,這樣有助於進一步區分null和undefined。
-
當一個資料不再需要使用時,我們最好通過將其值設定為null來釋放其引用,這個做法叫做解除引用。不過解除一個值的引用並不意味著自動回收改值所佔用的記憶體。解除引用的真正作用是讓值脫離執行環境,以便垃圾收集器在下次執行時將其回收。解除引用還有助於消除有可能出現的迴圈引用的情況。這一做法適用於大多數全域性變數和全域性物件的屬性,區域性變數會在它們離開執行環境時(函式執行完時)自動被解除引用。
2、特殊的typeof null
當我們使用typeof操作符檢測null值,我們理所應當地認為應該返"Null"型別呀,但是事實返回的型別卻是"object"。
var data = null;
console.log(typeof data); // "object"
複製程式碼
是不是很奇怪?其實我們可以從兩方面來理解這個結果:
-
一方面從邏輯角度來看,null值表示一個空物件指標,它代表的其實就是一個空物件,所以使用typeof操作符檢測時返回"object"也是可以理解的。
-
另一方面,其實在JavaScript 最初的實現中,JavaScript 中的值是由一個表示型別的標籤和實際資料值表示的(物件的型別標籤是 0)。由於 null 代表的是空指標(大多數平臺下值為 0x00),因此,null的型別標籤也成為了 0,typeof null就錯誤的返回了"object"。在ES6中,當時曾經有提案為歷史平凡, 將type null的值糾正為null, 但最後提案被拒了,所以還是保持"object"型別。
四、總結
用一句話總結兩者的區別就是:undefined 表示一個變數自然的、最原始的狀態值,而 null 則表示一個變數被人為的設定為空物件,而不是原始狀態。所以,在實際使用過程中,為了保證變數所代表的語義,不要對一個變數顯式的賦值 undefined,當需要釋放一個物件時,直接賦值為 null 即可。