天天看點

null 和 undefined 的差別探索javascript中null和undefined的深淵 譯

05 January 2014

當讨論JavaScript中的原始資料類型時,大多數人都知道的基本知識,從String,Number到Boolean。這些原始類型相當簡單,行為符合常識。但是,本文将更多聚焦獨特的原始資料類型Null和Undefined,是什麼讓他們如此相似,卻又似是而非。

在JavaScript中,<code>null</code>是字面量同時也是語言中的關鍵字,用來表示無法識别的對象值。換句話說,這用來表示“無值(no

value)”。雖然相似,<code>undefined</code>實際上代表了不存在的值(non-existence of a

value)。都是完全不可變的,沒有屬性和方法,也不能給其屬性指派。事實上,試圖通路或定義一個屬性将會引發一個類型錯誤(<code>TypeError</code>)。正如他們的名字暗示的那樣,他們是完全無效的值。

沒有值代表的布爾值是false,這意味着他們在條件上下文中會被被計算為false,如<code>if</code>語句。使用相等操作符(<code>==</code> )比較這兩個值和其他false值,他們并不等于除了自己:

盡管如此,和其他相似之處,但<code>null</code>和<code>undefined</code>并不是等價的。每個作為其獨特的類型的唯一成員,<code>undefined</code>是Undefined類型和<code>null</code>是Null類型。使用全等操作符(<code>===</code>)比較這兩個值,這要求類型和值都相等,下面證明這一點:

這是一個重要的差別,服務于不同的目的和理由。區分這兩個值,你可以認為<code>undefined</code>代表一個意想不到的沒有值而<code>null</code>作為預期沒有值的代表。

有許多的方法産生一個<code>undefined</code>值的代碼。它通常遇到當試圖通路一個不存在的值時。在這種情況下,在JavaScript這種動态的弱類型語言中,隻會預設傳回一個<code>undefined</code>值,而不是上升為一個錯誤。

任何聲明變量時沒有提供一個初始值,都會有一個為<code>undefined</code>的預設值:

當試圖通路一個不存在的對象屬性或數組項時,傳回一個<code>undefined</code>值:

如果省略了函數的傳回語句,傳回<code>undefined</code>:

函數調用時未提供的值結果将為<code>undefined</code>參數值:

<code>void</code>操作符也可以傳回一個<code>undefined</code>值。像Underscore的庫使用它作為一個防禦式的類型檢查,因為它是不可變的,可以在任何上下文依賴傳回<code>undefined</code>:

最後,<code>undefined</code>是一個預定義的全局變量(不像<code>null</code>關鍵字)初始化為<code>undefined</code>值:

ECMAScript 5中,這個變量是隻讀的,以前并非如此。

null的用例是使他與衆不同的主要方面,因為不像<code>undefined</code>,<code>null</code>被認為是更有用。這正是為什麼<code>typeof</code>操作符作用于<code>null</code>值時傳回“object”。最初的理由是,現在仍然是,通常用作一個空引用一個空對象的預期,就像一個占位符。<code>typeof</code>的這種行為已經被确認為一個錯誤,雖然提出了修正,出于後相容的目的,這一點已經保持不變。

這就是為什麼JavaScript環境從來沒有設定一個值為<code>null</code>;它必須以程式設計方式完成。正如文檔MDN所說:

在api中,<code>null</code>是經常檢索對象的地方可以預期,但沒有相關的對象。

這适用于DOM,它是獨立于語言的,不屬于ECMAScript規範的範圍。因為它是一個外部API,試圖擷取一個不存在的元素傳回一個<code>null</code>值,而不是<code>undefined</code>。

一般來說,如果你需要給一個變量或屬性指定一個不變值,将它傳遞給一個函數,或者從一個函數傳回<code>null</code>,<code>null</code>幾乎總是最好的選擇。簡而言之,JavaScript使用<code>undefined</code>并且程式員應該使用<code>null</code>。 <code>null</code>的另一個可行的用例,也被認為是良好的實踐是一個顯式指定變量為無效(<code>object= null</code>)當一個引用不再是必需的。通過配置設定<code>null</code>值,有效地清除引用,并假設對象沒有引用其他代碼,指定垃圾收集,確定回收記憶體。

使<code>null</code>和<code>undefined</code>像黑洞的不隻是他們的行為,而是在他們在JavaScript環境的内部的處理方式。他們似乎通常并不具有同樣的關聯特征與其他原生或内置對象。

在ES5中,<code>Object.prototype.toString</code>方法,已經成為實際的類型檢查标準,這在<code>null</code>和<code>undefined</code>中被證明是一緻的:

然而,<code>Object.prototype.toString</code>方法實際上并不是檢索<code>null</code>的内部<code>[[Class]]</code>屬性或<code>undefined</code>的公開構造函數。根據文檔,以下步驟發生在被調用過程中:

如果值是<code>undefined</code>,傳回“<code>[object Undefined]</code>”。

如果這個值為<code>null</code>,則傳回“<code>[object Null]</code>”。

讓O作為調用<code>ToObject</code>同時傳遞<code>this</code>值作為參數的結果值。

讓class是O的内部屬性<code>[[Class]]</code>的值。

傳回的結果連接配接三個字元串“<code>[object </code>”,class,和“<code>]</code>”的結果的字元串值。

該方法執行一個簡單的字元串傳回值,如果它檢測到<code>null</code>或<code>undefined</code>和其他對象統一的功能。在整個規範中這是很常見的,因為當遇到<code>null</code>和<code>undefined</code>值時大多數方法包含一個簡單的捕捉并傳回。事實上,沒有迹象表明他們包含與任何原生對象相關聯的内部屬性。就好像他們不是對象。我很想知道如果一個JavaScript的原生環境内部實際存在的顯式方案會怎樣?也許有人更熟悉一個可以參與的實作。

無論這些原生對象多麼不尋常,了解<code>null</code>和<code>undefined</code>之間的差異,和他們在JavaScript的語言基礎中截然不同的角色。它可能不能使你的應用程式有所突破,但是一般來說,它僅被證明在開發和調試中長期有益。

本文問翻譯文章,原文為“”

本文較難以了解,可參照原文便于了解。

原文位址:

譯文位址: