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