探索JavaScript中Null和Undefined的深淵
探索JavaScript中Null和Undefined的深淵
本文翻譯自:
https://modernweb.com/exploring-the-abyss-of-null-and-undefined-in-javascript/
在討論JavaScript中的原始數(shù)據(jù)類型時(shí),大多數(shù)人都了解基本知識(shí),從String,Number和Boolean開始。這些原語非常簡(jiǎn)單,可以像您期望的那樣起作用。但是,本文將重點(diǎn)介紹稱為Null和Undefined的更獨(dú)特的原始數(shù)據(jù)類型。是什么使它們相似,不相似以及總體上與眾不同。
了解 null 和 undefined
在JavaScript中,null是語言關(guān)鍵字,不代表可識(shí)別的對(duì)象值。換句話說,這表示“沒有值”。雖然相似,但undefined實(shí)際上表示值不存在。兩者都是完全不變的,沒有屬性或方法,并且無法進(jìn)行屬性分配。實(shí)際上,嘗試訪問或定義屬性會(huì)引發(fā)TypeError。顧名思義,它們完全沒有值。
值的缺失導(dǎo)致它們被描述為虛假值,這意味著當(dāng)它們?cè)跅l件(如if語句)的上下文中使用時(shí),它們的值為假。使用相等運(yùn)算符(==)將這兩個(gè)虛假值與其他虛假值進(jìn)行比較,可以發(fā)現(xiàn)它們除了自身之外不等于其他任何值:
null?==?0;?//?false
undefined?==?"";?//?false
null?==?false;?//?false
undefined?==?false;?//?false
null?==?undefined;?//?true
盡管有此與其他相似之處,null 和 undefined并不等效。每個(gè)都充當(dāng)其自己獨(dú)特類型的唯一成員;undefined是類型的未定義和null類型為空。將二者與值和類型均等的嚴(yán)格相等運(yùn)算符(===)進(jìn)行比較就足以證明:
undefined?===?null;?//?false
這是一個(gè)重要的區(qū)別; 兩者都有不同的目的,這樣做是合理的。為了區(qū)分兩者,您可能希望將其undefined視為代表值的意外缺失和null代表預(yù)期的值缺失。
屈服 undefined
undefined在代碼中產(chǎn)生值的方法有很多種。嘗試訪問不存在值的值時(shí)通常會(huì)遇到此問題。在這種情況下,JavaScript是一種動(dòng)態(tài)的,弱類型的語言,它將僅默認(rèn)為一個(gè)undefined值,而不會(huì)引發(fā)錯(cuò)誤。
任何未提供初始值的已聲明變量將具有默認(rèn)值undefined:
var?foo;?//?defaults?to?undefined
undefined嘗試訪問不存在的對(duì)象屬性或數(shù)組項(xiàng)時(shí),將發(fā)出一個(gè)值:
var?array?=?[1,?2,?3];
var?foo?=?array.foo;?//?foo?property?doesn't?exist,?returns?undefined
var?item?=?array[5];?//?no?item?exists?in?the?array?at?index?5,?returns?undefined
如果函數(shù)中省略了return語句,undefined則返回:
var?value?=?(function(){})();?//?returns?undefined
未提供給函數(shù)調(diào)用的undefined參數(shù):
(function(undefined){
????//?parameter?is?undefined
})();
該void 0還可以用來返回一個(gè)undefined值。諸如Underscore之類的庫將其用作類型檢查的防彈手段,因?yàn)樗遣豢勺兊模?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">undefined在任何情況下都可以依賴于返回:
function?isUndefined(obj){
????return?obj?===?void?0;
}
最后,undefined是一個(gè)預(yù)定義的全局變量(不是類似的關(guān)鍵字null),它已初始化為以下undefined值:
'undefined'?in?window;?//?true
從ECMAScript 5開始,此變量是只讀的,以前不是這種情況。
null 實(shí)例
用例null是將其區(qū)分的主要方面,因?yàn)榕c相比undefined,null它被視為更多的分配值。這就是為什么typeof運(yùn)算符與值一起使用時(shí)返回“對(duì)象”的原因null。最初的理由是,null過去和現(xiàn)在通常用作需要對(duì)象的空引用,非常類似于占位符。typeof此后,與之相關(guān)的這種行為已被識(shí)別為錯(cuò)誤,盡管已提出糾正建議,但出于向后兼容的目的,到目前為止,該行為未更改。
這就是JavaScript環(huán)境從不將值設(shè)置為的原因null。它必須以編程方式完成。正如有關(guān)MDN的文檔所述:
在API中,null通常是在可以期望有對(duì)象但沒有對(duì)象相關(guān)的地方進(jìn)行檢索。
對(duì)于DOM來說確實(shí)如此,它是獨(dú)立于語言的,并且不屬于ECMAScript規(guī)范的范圍。由于它是一個(gè)外部API,因此嘗試檢索不存在的元素會(huì)返回一個(gè)null值,而不是undefined。
通常,如果您需要為變量或?qū)傩苑峙浞侵担瑢⑵鋫鬟f給函數(shù)或從函數(shù)返回,null則幾乎總是最佳選擇。
另一個(gè)可行的用例null也被認(rèn)為是良好實(shí)踐,object = null當(dāng)不再需要引用時(shí),顯式變量無效。通過分配一個(gè)null值,您可以有效地清除引用,并假定未在代碼的其他位置引用該對(duì)象,將其指定為垃圾回收,從而回收內(nèi)存。
深層發(fā)掘
是什么讓null和undefined這樣的黑洞不僅僅是在他們的行為,而且在方式,他們?cè)趦?nèi)部JavaScript環(huán)境中進(jìn)行處理。它們似乎不具有通常與其他圖元或內(nèi)置對(duì)象關(guān)聯(lián)的相同特征。
作為ES5的,該Object.prototype.toString方法,這已成為進(jìn)行類型檢查的事實(shí)標(biāo)準(zhǔn),被證明是在這方面兩者一致的null和undefined:
Object.prototype.toString.call(null);?//?[object?Null]
Object.prototype.toString.call(undefined);?//?[object?Undefined]
但是,該Object.prototype.toString方法實(shí)際上并沒有檢索構(gòu)造函數(shù)的內(nèi)部[[Class]]屬性null或undefined公開其構(gòu)造函數(shù)。根據(jù)文檔,調(diào)用時(shí)將采取以下步驟:
If the this value is undefined, return "[object Undefined]". If the this value is null, return "[object Null]". Let O be the result of calling ToObject passing the this value as the argument. Let class be the value of the [[Class]] internal property of O. Return the String value that is the result of concatenating the three Strings "[object ", class, and "]".
