Undefined與Null的區(qū)別

一、基本數(shù)據(jù)類型

在介紹undefined與null之前,我們先來(lái)了解一下ECMAScript中的數(shù)據(jù)類型。在ECMAScript中有六種簡(jiǎn)單數(shù)據(jù)類型(也稱為基本數(shù)據(jù)類型): Undefined、Null、Boolean、Number 和 String、Symbol (ES6中引入) 。還有一種復(fù)雜數(shù)據(jù)類型——Object。

Undefined和Null都只有一個(gè)值,分別對(duì)應(yīng)著undefined和null。這兩種不同類型的值,既有著不同的語(yǔ)義和場(chǎng)景,又表現(xiàn)出較為相似的行為。

二、undefined

undefined 的字面意思就是:未定義的值 。這個(gè)值的語(yǔ)義是,希望表示一個(gè)變量最原始的狀態(tài),而非人為操作的結(jié)果 。?這種原始狀態(tài)會(huì)在以下 4 種場(chǎng)景中出現(xiàn):

1、聲明一個(gè)變量,但是沒(méi)有賦值

var foo;

console.log(foo); // undefined

訪問(wèn) foo,返回了 undefined,表示這個(gè)變量自從聲明了以后,就從來(lái)沒(méi)有使用過(guò),也沒(méi)有定義過(guò)任何有效的值。

2、訪問(wèn)對(duì)象上不存在的屬性或者未定義的變量

console.log(Object.foo); // undefined

console.log(typeof demo); // undefined

訪問(wèn) Object 對(duì)象上的 foo 屬性,返回 undefined , 表示Object 上不存在或者沒(méi)有定義名為 foo 的屬性;對(duì)未聲明的變量執(zhí)行typeof操作符返回了undefined值。

3、函數(shù)定義了形參,但沒(méi)有傳遞實(shí)參

// 函數(shù)定義了形參a

function fn(a) {

? ? console.log(a); // undefined

}

fn(); //未傳遞實(shí)參

函數(shù) fn 定義了形參 a,但 fn 被調(diào)用時(shí)沒(méi)有傳遞參數(shù),因此,fn 運(yùn)行時(shí)的參數(shù) a 就是一個(gè)原始的、未被賦值的變量。

4、使用void對(duì)表達(dá)式求值

void false; // undefined

void 0; // undefined

void []; // undefined

void null; // undefined

void function fn(){} ; // undefined

ECMAScript 明確規(guī)定 void 操作符 對(duì)任何表達(dá)式求值都返回 undefined ,這和函數(shù)執(zhí)行操作后沒(méi)有返回值的作用是一樣的,JavaScript 中的函數(shù)都有返回值,當(dāng)沒(méi)有 return 操作時(shí),就默認(rèn)返回一個(gè)原始的狀態(tài)值,這個(gè)值就是 undefined,表明函數(shù)的返回值未被定義。

因此,undefined 一般都來(lái)自于某個(gè)表達(dá)式最原始的狀態(tài)值,不是人為操作的結(jié)果。當(dāng)然,你也可以手動(dòng)給一個(gè)變量賦值 undefined,但這樣做沒(méi)有意義,因?yàn)橐粋€(gè)變量不賦值就是 undefined 。


三、null

null 的字面意思是:空值 。這個(gè)值的語(yǔ)義是,希望表示一個(gè)對(duì)象被人為的重置為空對(duì)象,而非一個(gè)變量最原始的狀態(tài) 。在內(nèi)存里的表示就是,棧中的變量沒(méi)有指向堆中的內(nèi)存對(duì)象。

1、一般在以下兩種情況下我們會(huì)將變量賦值為null

如果定義的變量在將來(lái)用于保存對(duì)象,那么最好將該變量初始化為null,而不是其他值。換句話說(shuō),只要意在保存對(duì)象的變量還沒(méi)有真正保存對(duì)象,就應(yīng)該明確地讓該變量保存null值,這樣有助于進(jìn)一步區(qū)分null和undefined。

當(dāng)一個(gè)數(shù)據(jù)不再需要使用時(shí),我們最好通過(guò)將其值設(shè)置為null來(lái)釋放其引用,這個(gè)做法叫做解除引用。不過(guò)解除一個(gè)值的引用并不意味著自動(dòng)回收改值所占用的內(nèi)存。解除引用的真正作用是讓值脫離執(zhí)行環(huán)境,以便垃圾收集器在下次運(yùn)行時(shí)將其回收。解除引用還有助于消除有可能出現(xiàn)的循環(huán)引用的情況。這一做法適用于大多數(shù)全局變量和全局對(duì)象的屬性,局部變量會(huì)在它們離開(kāi)執(zhí)行環(huán)境時(shí)(函數(shù)執(zhí)行完時(shí))自動(dòng)被解除引用。

2、特殊的typeof null

當(dāng)我們使用typeof操作符檢測(cè)null值,我們理所應(yīng)當(dāng)?shù)卣J(rèn)為應(yīng)該返"Null"類型呀,但是事實(shí)返回的類型卻是"object"。

var data = null;

console.log(typeof data); // "object"

是不是很奇怪?其實(shí)我們可以從兩方面來(lái)理解這個(gè)結(jié)果:

一方面從邏輯角度來(lái)看,null值表示一個(gè)空對(duì)象指針,它代表的其實(shí)就是一個(gè)空對(duì)象,所以使用typeof操作符檢測(cè)時(shí)返回"object"也是可以理解的。

另一方面,其實(shí)在JavaScript 最初的實(shí)現(xiàn)中,JavaScript 中的值是由一個(gè)表示類型的標(biāo)簽和實(shí)際數(shù)據(jù)值表示的(對(duì)象的類型標(biāo)簽是 0)。由于 null 代表的是空指針(大多數(shù)平臺(tái)下值為 0x00),因此,null的類型標(biāo)簽也成為了 0,typeof null就錯(cuò)誤的返回了"object"。在ES6中,當(dāng)時(shí)曾經(jīng)有提案為歷史平凡, 將type null的值糾正為null, 但最后提案被拒了,所以還是保持"object"類型。

四、總結(jié)

用一句話總結(jié)兩者的區(qū)別就是:undefined 表示一個(gè)變量自然的、最原始的狀態(tài)值,而 null 則表示一個(gè)變量被人為的設(shè)置為空對(duì)象,而不是原始狀態(tài)。所以,在實(shí)際使用過(guò)程中,為了保證變量所代表的語(yǔ)義,不要對(duì)一個(gè)變量顯式的賦值 undefined,當(dāng)需要釋放一個(gè)對(duì)象時(shí),直接賦值為 null 即可。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容