一文讓你徹底弄懂js中undefined和null的區(qū)別
前言
undefined 和 null 的區(qū)別是個老生常談的話題了,之前我對二者的區(qū)別只是簡單理解,例如二者轉(zhuǎn)成 Boolean 類型都是 false、使用 == 進(jìn)行比較時為 true、使用 === 進(jìn)行比較時為 false 等,卻沒有真正系統(tǒng)地總結(jié)二者的區(qū)別。
某天,下班前幾分鐘,我徹底弄懂了 undefined 和 null 的區(qū)別。
一、基本概念
1、undefined
undefined 是“全局對象”的一個屬性。也就是說,它是全局作用域的一個變量(下面展開對 undefined 變量的賦值操作)。undefined 的最初值就是原始數(shù)據(jù)類型 undefined。
2、null
null 是一個字面量,不像 undefined,它不是“全局對象”的一個屬性。null 是表示缺少的標(biāo)識,指示變量未指向任何對象。把 null 作為尚未創(chuàng)建的對象,或許更好理解。在 API 中,null 常使用來表示返回類型應(yīng)是一個對象,但沒有關(guān)聯(lián)某個具體對象的這么一個值。
二、簡單區(qū)別
總的來說,null 和 undefined 都表示空,主要區(qū)別在于 undefined 表示尚未初始化的變量的值,而 null 表示該變量有意缺少對象指向。
undefined
- 這個變量從根本上就沒有定義。
- 隱藏式 空值。
null
- 這個值雖然定義了,但它并未指向任何內(nèi)存中的對象。
- 聲明式 空值。
以下是一張經(jīng)典的圖片,幫助我們理解。
三、表現(xiàn)形式
undefined 和 null 在 JavaScript 中有什么不同的表現(xiàn)形式,理解這些表現(xiàn)形式,可以幫助我們更好地理解 undefined 和 null 的區(qū)別。
1、typeof
console.log(typeof undefined); // 'undefined' console.log(typeof null); // 'object'
typeof null 為 object 是一個歷史遺留問題,直到現(xiàn)階段都無法被修復(fù)。
在 JavaScript 初始版本中,值以 32位 存儲。前 3位 表示數(shù)據(jù)類型的標(biāo)記,其余位則表示值。
對于所有對象類型,它的前 3位 都以 000 作為類型標(biāo)記位。在 JavaScript 早期版本中,null 被認(rèn)為是一個特殊的值,用來對應(yīng) C 中的空指針,但 JavaScript 中沒有 C 中的指針概念,所以 null 意味著什么都沒有或者 void 并以 全0(32位)表示。
因此每當(dāng) JavaScript 讀取 null 時,它的前 3位 將它視為對象類型,這也是為什么 typeof null 返回 object 的原因。
2、== 與 ===
console.log(null == undefined); // true console.log(null === undefined); // false console.log(!!null === !!undefined); // true
這一點相信大家都明白,== 比較的是值,而 === 比較的是值跟類型。undefined 和 null 的布爾值都為 false,因此在用 == 比較時,為 true;而 undefined 和 null 的類型不同,因此在用 === 比較時為 false。
3、Object.prototype.toString.call
console.log( Object.prototype.toString.call(undefined) ); // '[object Undefined]' console.log( Object.prototype.toString.call(null) ); // '[object Null]'
toString() 是 Object 的原型方法,調(diào)用該方法,默認(rèn)返回當(dāng)前對象的 [[Class]]。這是一個內(nèi)部屬性,其格式為 [object Xxx],其中 Xxx 就是對象的類型。
那么既然在 JavaScript 中,萬物皆對象,為什么 xxx.toString() 不能返回變量類型?
這是因為各個類中重寫了 toString(),因此需要調(diào)用 Object 中的 toString(),且必須使用 toString.call() 的方式調(diào)用。對于 Object 對象,直接調(diào)用 toString() 就能返回 [object Object];而對于其他對象,則需要通過 call / apply 來調(diào)用才能返回正確的類型信息。
4、+ 運(yùn)算 與 Number()
let a = undefined + 1; let b = null + 1; console.log(a); // NaN console.log(b); // 1 console.log(Number(undefined)); // NaN console.log(Number(null)); // 0
這涉及到 JavaScript 中的隱式類型轉(zhuǎn)換,在執(zhí)行加法運(yùn)算前,隱式類型轉(zhuǎn)換會嘗試將表達(dá)式中的變量轉(zhuǎn)換為 number 類型。如:'1' + 1 會得到結(jié)果 11。
null 轉(zhuǎn)化為 number 時,會轉(zhuǎn)換成 0。
undefined 轉(zhuǎn)換為 number 時,會轉(zhuǎn)換為 NaN。
5、JSON.stringify
console.log( JSON.stringify({a: undefined}) ); // '{}' console.log( JSON.stringify({b: null}) ); // '{b: null}' console.log( JSON.stringify({a: undefined, b: null}) ); // '{b: null}'
JSON 會將 undefined 對應(yīng)的 key 刪除,這是因為 JSON 自身的轉(zhuǎn)換原則。在 undefined 的情況下,有無該條數(shù)據(jù)是沒有區(qū)別的,因為他們在表現(xiàn)形式上并無不同。
let obj1 = { a: undefined }; let obj2 = {}; console.log(obj1.a); // undefined console.log(obj2.a); // undefined
6、let undefiend = 'test'
function test(params) { let undefined = 'test'; // 該作用域內(nèi)undefined為一個變量,賦值為test return params === undefined; } test(); // false test(undefined); // false test('test'); // ture let undefined = 'test'; // Uncaught SyntaxError: Identifier 'undefined' has already been declared
JavaScript 對于 undefined 的限制方式為全局創(chuàng)建了一個只讀的 undefined,但是并沒有徹底禁止局部 undefined 變量的定義。
請在任何時候,都不要對 undefined 變量進(jìn)行覆蓋,就算是你的 JSON 轉(zhuǎn)換將 undefined 轉(zhuǎn)換為 '' ,也不要通過該操作進(jìn)行,這將是及其危險的行為。
四、建議
如果你需要使用 undefined 定義空值,請不要采取以下兩種方式:
- let a;
- let a = undefined;
進(jìn)而采取下面這種方式顯式聲明 undefined:
- let a = void 0;
附:null在類型判斷時為什么是object
這是一段歷史,1995年Javascript誕生之初, 在實現(xiàn)js類型判斷的方法時(也就是typeof),數(shù)值是以32位存儲的,由標(biāo)志位(1~3位)和數(shù)值組成。標(biāo)志位存儲的是低位的數(shù)據(jù)。這里有五種標(biāo)志位:
- 000 表示對象
- 1 表示整數(shù)
- 010 表示浮點數(shù)
- 100 表示字符串
- 110 表示布爾類型
有兩個特殊值:
- undefined用-2^30表示
- null用全0表示
這不巧了嗎這不是,null的低位也是000,所以誤打誤撞成為了object,這一點一直被認(rèn)為是個bug,直到es6的時候typeof null === 'null'的提案被否決,typeof null === 'object'變成了feature,也就是說這個"bug"不會被“修復(fù)”了
總結(jié)
到此這篇關(guān)于undefined和null區(qū)別的文章就介紹到這了,更多相關(guān)undefined和null的區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- javascript中undefined與null的區(qū)別
- JavaScript undefined及null區(qū)別實例解析
- JavaScript中undefined和null的區(qū)別
- javascript中undefined與null的區(qū)別
- JavaScript中Null與Undefined的區(qū)別解析
- JavaScript中的null和undefined區(qū)別介紹
- 詳解JavaScript中undefined與null的區(qū)別
- js中 關(guān)于undefined和null的區(qū)別介紹
- JS基礎(chǔ)之undefined與null的區(qū)別分析
- JS中null和undefined的區(qū)別
相關(guān)文章
JS 對象(Object)和字符串(String)互轉(zhuǎn)方法
下面小編就為大家?guī)硪黄狫S 對象(Object)和字符串(String)互轉(zhuǎn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-05-05javascript 操作文件 實現(xiàn)方法小結(jié)
可以通過瀏覽器在訪問者的硬盤上創(chuàng)建文件 JavaScript操作文件系統(tǒng)創(chuàng)建快捷方式2009-07-07JS如何通過FileReader獲取.txt文件內(nèi)容
今天小編就為大家分享一篇JS如何通過FileReader獲取.txt文件內(nèi)容,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12document.getElementById方法在Firefox與IE中的區(qū)別
相信很多朋友在寫JavaScript的時候,對瀏覽器的兼容問題會感到很頭疼。這不,煩什么,什么就來了,特記錄下來,與大家分享。2010-05-05JS獲取子窗口中返回的數(shù)據(jù)實現(xiàn)方法
下面小編就為大家?guī)硪黄狫S獲取子窗口中返回的數(shù)據(jù)實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-05-05