typeof 是一個 運算子(operator),Return a String
。
當我們用
typeof
operator, 我們真正問的問題是
「 現在在變數(v)裡面的『值』,它的型別是什麼?」
而不是要問的變數 v
的型別是什麼。
(變數沒有型別,值才有)
有些時候,我們使用 Object.prototype.toString.call
加上正規運算式和陣列以區分型別最後的回傳,而非 typeof operator。
因為 typeof operator 的結果和型別並 沒有一一對應
。
typeof undefined === "undefined"; // true , 回傳是字串不是 undefined
typeof true === "boolean"; // true
typeof 42 === "number"; // true
typeof "42" === "string"; // true
typeof { life: 42 } === "object"; // true
// 在 ES6 中被加入的!
typeof Symbol() === "symbol"; // true
and
typeof null === "object"; // true, oops!
typeof function a(){ /* .. */ } === "function"; // true , hmmmm?
typeof [1,2,3] === "object"; // true, hmmmm?
理論上回傳值都要是左邊 Type of val 的值(top level type),但基於一些歷史原因
,有些著名的 bug 被留下來。
Null 回傳 Object 是一個 Bug
Function 回傳 不是 Object
回傳是一個 "function"
, 他是 "function"拿不到 typeof 回傳是一個 "Array"
,因為會回傳 "Object"對 Host object 使用 typeof
Reference code : MDN
typeof new Boolean(true) === 'object'; // 這樣會令人混淆。不要這樣用!
typeof new Number(1) === 'object'; // 這樣會令人混淆。不要這樣用!
typeof new String("abc") === 'object'; // 這樣會令人混淆。不要這樣用!
typeof Boolean(true) === 'boolean'; // 但是不要使用這種方式!
typeof Number(1) === 'number'; // 但是不要使用這種方式!
typeof String("abc") === 'string'; // 但是不要使用這種方式!
// 對於 Array
typeof [1, 2, 4] === 'object'; // 請使用 Array.isArray 或者 Object.prototype.toString.call 以區分正規運算式和陣列
對於 Host object 可能是 undefined
Host object 回傳應該是取決於執行當下的環境(provided by the JS environment),但瀏覽器回傳 'undefined' 是一個 刻意的違規(willful violation)。
(typeof bug 夠多了,web standards還故意來鬧 = = )
原本 typeof 應該必定回傳 string
,但 ES6 使用 let / const 之類的語法有可能產生 Error
中斷程式。
後面文章會提到 let / const 的 TDZ error 問題
Reference : mdn typeof - Error
這邊花一點篇幅再補充一下 undefined
有,且只有一個值
(aka 存在且唯一),稱為 undefined 。在我們思考 typeof 的值時,其實在意的不是 變數 v
的 type(文章開始有提過)。
所以 line 2 回傳的型別,可以視為是一種 沒有 assign 任何值(value) 的 預設(default)
,
稱作 undefined (此處 undefined -> value)。
因為 剛好
這個預設值 (value) 和 undefined type
的值一樣,
所以我們判斷這個型別也是 undefined ( 此處 undefined -> type )。
還有一個很常見的狀況是,這個 變數 v
可能會 assign 其他值,此時 變數(v) 的型別就是 「值」 的型別。
但有時候 變數(v) 會被設定回 undefined 當作把值清空 ,
You set it to undefined, you undefine it.。
上述這種情況很常見,因為你沒有刪除 (delete) 變數,
也沒有移除 (remove) 變數, 變數(v) 也不會莫名其妙消失。
所以讓 變數 回歸 一開始 「沒有 assign 任何值的預設 」的狀態,
這個狀態的「值」就是 undefined (value)。
因為值是 undefined,所以我們判斷型別也是 undefined。
這個是 Kyle Simpson 用 JS 的慣例,把變數清空用 undefined 。 有些人可能是用 null。
undefined 沒有任何方法、沒有任何相應的“包裝物件(wrapper objects)”,所以可以說他是「最原始的 (the most primitive) 」之一 ( 另一個是 null )。
alert(undefined.test); // error
null表示"沒有物件",即該處不應該有值。
Object.getPrototypeOf(Object.prototype)
undefined表示"缺少值",就是此處應該有一個值,但是還沒有定義。典型用法是:
作者傾向 NaN / undefined 的結果顯示的語意 (後文會提到 NaN)
undefined 代表的是「(此變數) 還沒有給值,所以不知道是什麼」
null 代表的是「(此變數可能曾經有值,可能沒有值) 現在沒有值」
我想這點在透過 Number() 強製為兩者轉型的時候多少可以看出點什麼:
Number( null ); // 0
Number( undefined ); // NaN