[教學]undefined與null的比較
null的型別居然是object!這是Bug啊~這是Bug啊~這是Bug啊~
前言
今天繼續來打底練基礎~本次要來聊聊undefined
、not defined
、null
,這些看起來就像「沒有」一樣,實際上他們之間可是差很多的哩!有些在時候會相等,有些時候又不一樣,那就跟著腳步一起看下去吧~~
目錄:
使用型態比較
在寫JS時有兩大型別,分別是基本型別(Primitives)與物件型別(Object)。
- 基本型別:
string
、number
、boolean
、null
、undefined
、symbol
- 物件型別:
array
、object
、function
……
在這裡可以觀察到本次要探討的null
、undefined
均出現在基本型別中。而基本型別裡都有「原始值 (primitive value)」,原始值是無法經過更改的的,例如布林值只有truth
、false
,不會再有其他的值,因此null
、undefined
也是一樣,null
型別只有一種值,就是 null
,而 undefined
類型也只有一種值,就是 undefined
。
我們透過程式碼來更進一步了解兩者之間的差異,首先分別給他們型別:
undefined
代表根本沒有這個東西,所以不知道這是什麼;null
代表此變數(可能曾經有值,可能沒有值)現在沒有值。
接著再用typeof
來檢驗型別是不是undefined
跟null
:
可以知道undefined
的型別是 undefined
,null
的型別是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 likeundefined
can be)…
翻成白話文的意思就是「null
是刻意指出一個值是『不存在的狀態』」,因此視為物件,只是它是個沒有值的物件(沒有值的意思不是0喔)。
我這裡將兩者分別理解為:「undefined
代表變數尚未被指派,呈現『尚未初始化的狀態』,因此型態為undefined
;null
代表變數已經被指派,但指派的值呈現『不存在的狀態』,因為已經被指派過了只是值尚未得知,若有值,型態就是object
」
null
的型態為object
確實是強詞奪理,它其實就是有bug,而官方文件也有說這就是bug,此型態應該要是null
才對!我們也只好先這樣接受了,也許等哪天就會改回來也說不一定(但修正會牽扯太多,我想這輩子應該是看不到吧)。
到這裡先兩者的比較就先告個段落,因為我們要來認識新的東西,之後再比較才不會搞不清楚狀況。
truthy與falsy
JS有truthy
的概念,在某些情況下會被推斷為true
,例如下列程式碼:
有時候我們在寫if else等判斷式,寫的會像上面的程式碼一樣。這裡的123
就代表著true
,這就是truthy
。truthy
的概念就像是「世間萬物皆有更古不變的道理,本就如此,而truthy
就是如此,反之亦然」。以下有列表顯示在哪些情況下為truthy
,而又在哪些情況下代表falsy
:
truthy 狀態 |
falsy 狀態 |
|
---|---|---|
布林值(Boolean) | true | false |
字串(string) | 除了空字串以外的字串 | 空字串 |
數字(number) | 除了0之外的任意值 | 0 |
null、undefined | 不可能 | 永遠 |
任何物件,包含{} 、[] |
永遠 | 不可能 |
這裡有個簡單的概念:「所有的物件都是truthy
, 只有空字串、數字0、undefined和 null 會是falsy
, 其餘的都是 truthy
。」這裡要特別留意就算是「boolean
(false)」它在if
判斷之下,仍然為true
喔!
補充了有關truthy
、falsy
的知識點後,我們就可以繼續做比較了。
使用一般相等與嚴格相等比較
等等我們會使用一般相等與嚴格相等來比較undefined
、null
是否相等。首先來看看一般相等與嚴格相等的差異:
符號 | 說明 | |
---|---|---|
一般相等(equality operator) | == |
將比較值轉換成同型別後比較,再比較兩者的值。(如字串8等同於數字8) |
一般不相等 | != |
將比較值轉換成同型別後比較,再比較兩者的值,值不同視為不相等。(如字串8不等同於數字7) |
嚴格相等(identity operator) | === |
先看型別再看值,兩者的值不會轉換型別。 |
嚴格不相等 | !== |
兩個不同型別的值,視為不相等。(如字串8不等同於數字8) |
一般相等允許在等價性比較中進行強制轉換;嚴格相等則不允許強制轉換。
知道一般相等是比較值、嚴格相等比較型態和值(不能全然這樣說,正確說法是上面那條,這裡僅以大概的意思去詮釋)後,我們可以來做比較了:
這裡使用一般相等來比較,兩者在轉換完型態後,其值是相等的。這裡我推測這是跟剛剛講的truthy
、falsy
有關,由於undefined
和null
都是falsy
值,因此兩個falsy
相等,得出的是true
。
為了避免被強制轉型,這裡建議使用嚴格相等來做比較:
這就比較正常了~嚴格相等從型別先下手,兩者的型別一個是undefined
一個是object
,是完全不同的,當然就不一樣囉!
使用數字運算比較
前面透過型別、運算子來做比較,現在我們來用算數來比較它們的差異:
undefined
與任意數字運算都會是 NaN (Not a number);null
與任意數字運算時,null
代表的值會是 0,因此可以運算。
undefined與not defined的差別
這兩個都跟defined有關,但是卻是兩個完全不一樣的概念,前者已經知道是已給定變數名稱,卻還未賦值,英文直譯為『尚未被定義』;後者是「完全沒有者個東西~它連變數也沒有,哪來的定義可言,根本不存在」,因此為『沒有被定義』。
undefined居然可以當作變數名稱或參數使用
驚不驚喜,意不意外~我們常說不能拿保留字當作變數,沒想到undefined
居然打破這個限制!!!在非全域作用範圍下, undefined
允許被當成變數名稱,而且變數的值是可以被修改的:
此舉雖然是合法的,但請不要使用好嗎?這樣會搞死一堆人 (除非你想欉康你的同事
結語
講了這麼多,希望有幫助到各位了解undefined
與null
之間的差異,以下是整理表格:
值 | 型別 | truthy or falsy |
運算 | 當變數名稱、參數 | |
---|---|---|---|---|---|
undefined |
undefined |
undefined |
falsy |
不能轉為數字並運算,會回傳NaN | 可以 |
null |
null |
object |
falsy |
可以轉為數字0運算 | 不可以 |
- 一般相等:相同,同為
falsy
值。 - 嚴格相等:不同,
undefined
與object
是不同的型別。
參考資料:
ㄟ問你喔,null, undefined 和 not defined 是差在哪?
Javascript 基礎打底系列 (二) - null、undefined、NaN 的差異與檢查方式