大頭照

你好,我是米米

菜雞前端工程師

[教學]undefined與null的比較

null的型別居然是object!這是Bug啊~這是Bug啊~這是Bug啊~

米米

JS、undefined與null的差異

前言

今天繼續來打底練基礎~本次要來聊聊undefinednot definednull,這些看起來就像「沒有」一樣,實際上他們之間可是差很多的哩!有些在時候會相等,有些時候又不一樣,那就跟著腳步一起看下去吧~~

目錄:

使用型態比較

在寫JS時有兩大型別,分別是基本型別(Primitives)物件型別(Object)

  • 基本型別: stringnumberbooleannullundefinedsymbol
  • 物件型別:arrayobjectfunction……

在這裡可以觀察到本次要探討的nullundefined均出現在基本型別中。而基本型別裡都有「原始值 (primitive value)」,原始值是無法經過更改的的,例如布林值只有truthfalse,不會再有其他的值,因此nullundefined也是一樣,null 型別只有一種值,就是 null ,而 undefined 類型也只有一種值,就是 undefined

我們透過程式碼來更進一步了解兩者之間的差異,首先分別給他們型別:

undefined代表根本沒有這個東西,所以不知道這是什麼;null代表此變數(可能曾經有值,可能沒有值)現在沒有值。

接著再用typeof來檢驗型別是不是undefinednull:

可以知道undefined 的型別是 undefinednull的型別是object

誒,不是誒!剛剛不是說null 型別只有一種值,就是 null ?怎麼變成object?說變就變,不講武德誒!!!

既然有問題我們就去找找,從官方文件MDN Web Docs有說:

The value null represents the intentional absence of any object value…

The value null is written with a literal, null (it’s not an identifer for a property of the global object like undefined can be)…

翻成白話文的意思就是「null是刻意指出一個值是『不存在的狀態』」,因此視為物件,只是它是個沒有值的物件(沒有值的意思不是0喔)。

我這裡將兩者分別理解為:「undefined代表變數尚未被指派,呈現『尚未初始化的狀態』,因此型態為undefinednull代表變數已經被指派,但指派的值呈現『不存在的狀態』,因為已經被指派過了只是值尚未得知,若有值,型態就是object

null的型態為object確實是強詞奪理,它其實就是有bug,而官方文件也有說這就是bug,此型態應該要是null才對!我們也只好先這樣接受了,也許等哪天就會改回來也說不一定(但修正會牽扯太多,我想這輩子應該是看不到吧)

到這裡先兩者的比較就先告個段落,因為我們要來認識新的東西,之後再比較才不會搞不清楚狀況。

truthy與falsy

JS有truthy的概念,在某些情況下會被推斷為true,例如下列程式碼:

有時候我們在寫if else等判斷式,寫的會像上面的程式碼一樣。這裡的123就代表著true,這就是truthytruthy的概念就像是「世間萬物皆有更古不變的道理,本就如此,而truthy就是如此,反之亦然」。以下有列表顯示在哪些情況下為truthy,而又在哪些情況下代表falsy

truthy狀態 falsy狀態
布林值(Boolean) true false
字串(string) 除了空字串以外的字串 空字串
數字(number) 除了0之外的任意值 0
null、undefined 不可能 永遠
任何物件,包含{}[] 永遠 不可能

這裡有個簡單的概念:「所有的物件都是truthy, 只有空字串數字0undefinednull 會是falsy, 其餘的都是 truthy。」這裡要特別留意就算是「boolean(false)」它在if判斷之下,仍然為true喔!

補充了有關truthyfalsy的知識點後,我們就可以繼續做比較了。

使用一般相等與嚴格相等比較

等等我們會使用一般相等與嚴格相等來比較undefinednull是否相等。首先來看看一般相等與嚴格相等的差異:

符號 說明
一般相等(equality operator) == 將比較值轉換成同型別後比較,再比較兩者的值。(如字串8等同於數字8)
一般不相等 != 將比較值轉換成同型別後比較,再比較兩者的值,值不同視為不相等。(如字串8不等同於數字7)
嚴格相等(identity operator) === 先看型別再看值,兩者的值不會轉換型別。
嚴格不相等 !== 兩個不同型別的值,視為不相等。(如字串8不等同於數字8)

一般相等允許在等價性比較中進行強制轉換;嚴格相等則不允許強制轉換。

知道一般相等是比較值、嚴格相等比較型態和值(不能全然這樣說,正確說法是上面那條,這裡僅以大概的意思去詮釋)後,我們可以來做比較了:

這裡使用一般相等來比較,兩者在轉換完型態後,其值是相等的。這裡我推測這是跟剛剛講的truthyfalsy有關,由於undefinednull都是falsy值,因此兩個falsy相等,得出的是true

為了避免被強制轉型,這裡建議使用嚴格相等來做比較:

這就比較正常了~嚴格相等從型別先下手,兩者的型別一個是undefined一個是object,是完全不同的,當然就不一樣囉!

使用數字運算比較

前面透過型別、運算子來做比較,現在我們來用算數來比較它們的差異:

undefined與任意數字運算都會是 NaN (Not a number);null與任意數字運算時,null代表的值會是 0,因此可以運算。

undefined與not defined的差別

這兩個都跟defined有關,但是卻是兩個完全不一樣的概念,前者已經知道是已給定變數名稱,卻還未賦值,英文直譯為『尚未被定義』;後者是「完全沒有者個東西~它連變數也沒有,哪來的定義可言,根本不存在」,因此為『沒有被定義』。

undefined居然可以當作變數名稱或參數使用

驚不驚喜,意不意外~我們常說不能拿保留字當作變數,沒想到undefined居然打破這個限制!!!在非全域作用範圍下, undefined允許被當成變數名稱,而且變數的值是可以被修改的:

此舉雖然是合法的,但請不要使用好嗎?這樣會搞死一堆人 (除非你想欉康你的同事

結語

講了這麼多,希望有幫助到各位了解undefinednull之間的差異,以下是整理表格:

型別 truthy or falsy 運算 當變數名稱、參數
undefined undefined undefined falsy 不能轉為數字並運算,會回傳NaN 可以
null null object falsy 可以轉為數字0運算 不可以
  • 一般相等:相同,同為falsy值。
  • 嚴格相等:不同,undefinedobject是不同的型別。

參考資料:

ㄟ問你喔,null, undefined 和 not defined 是差在哪?

Javascript 基礎打底系列 (二) - null、undefined、NaN 的差異與檢查方式

重新認識 JavaScript: Day 03 變數與資料型別

第29天-Truthy和Falsy

感謝抖內

BUY ME A COFFEE
comments powered by Disqus
comments powered by Disqus

advertisement

recent post

categories

advertisement

about

你好,我是米米,是個剛畢業就已經成為社畜的前端工程師==