淺談類型判斷 in JavaScript
( image via Franco Folini )
JavaScript 中如何正確的判斷類型,這東西也許基本,但其實隱藏了許多細節,雖然已經 2013 年了,但是這個看似簡單的問題在 JavaScript 中也許不會有正確且單一的答案。
在 JavaScript 中判斷類型,有非常多種選擇,但要記住,絕對不要只選用一種方式來判斷類型,因為不管是哪種選擇,都有其特異的行為與例外,適當的選擇變數的判斷方式,在 JavaScript 的寫作中是非常重要的。
typeof
其實光是 typeof
這個方法就可以花整整一個篇幅來講,有太多的事蹟可以說嘴了:
1 2 3 4 5 6 7 8 |
|
上面是段常見的 JavaScript code,運用 typeof
來判斷變數的型態,但當你用 typeof
習慣之後,你會發現有趣的事:
1 2 3 4 5 6 |
|
It’s work!以上這些情況,看來都沒有什麼問題,但是:
1
|
|
一個 array 是 object
,這並非錯誤的結果,但這表示我們必須要另外的條件去判斷 array
,不過如果是下面這樣呢:
1
|
|
部分關於
typeof null
的討論,有興趣可以看看 proposals 跟 discussion
不過 V8 engine 倒是有提供選項修正這件事,可以試試看使用 --harmony_typeof
這個選項
1 2 3 4 |
|
--harmony_typeof
在 V8 中是一個獨立的 option 而不是被整併在 --harmony
,這部份可以看看 harmony:typeof_null 的討論;就像 Douglas Crockford 講到的:
I like this fix. New code will definitely be better for it. But the old code breaks.
這樣的修正由於影響了太多舊有的程式,因此在 Harmony 中是被 reject 了。
看來大家應該了解到了,在 JavaScript 中,單單運用 typeof
是不足的,看起來甚至有點滑稽,日子一過,時間一久,是人都會撞到一兩個雷,所以你最好離他遠遠的。
1
|
|
為什麼
typeof NaN
是number
呢?這是因為 ECMAScript 標準規定 Number 必須是 IEEE-754 浮點數,這之中包含了兩個特殊數值:Infinity
,NaN
instanceof
那麼 instanceof
這個方法呢?用以判斷物件本身繼承何種類型,但這個操作符有其運作的限制,底下我們來看個例子:
1 2 3 4 |
|
上面跟 Object
有關的情況下運作都非常正常,但下面的狀況就不一樣了:
1 2 3 4 |
|
這邊要提到的是,JavaScript 中的基本型別,是無法以 instanceof
來判別的。
基本型別:string、number、boolean
但可以這樣寫
1 2 |
|
不過這樣的程式沒什麼意義,因為你早就知道他是什麼型別的了 :)
constructor
或是我們可以使用 constructor
屬性來判斷
1 2 3 4 |
|
不過 constructor
也有運用上的難題,那就是無法合理的判斷繼承的類型:
1 2 3 4 |
|
而現今大部分的 js lib (or framework) 都有自己實作繼承的方法,可謂其濫觴。
你會需要這本書:JavaScript Patterns, Stoyan Stefanov, 2010.
另外如果是跟瀏覽器打交道的前端工程師,在這部份需要的知道的是,不同 Window 之間的物件體系是各自獨立的:
1 2 3 |
|
你的 Array
可不是我的 Array
啊!
Object.prototype.toString
前面我們提到了可以運用 constructor
屬性來判定物件類型,讓我們再來講講 Object.protype.toString
這個方法
1 2 3 4 |
|
運用這種方式我們可以正確的判斷一個變數的基本型態,但是如果是自訂類型的話,卻無法得知真正的類型,因為結果依然會是 [object Object]
小結
在 JavaScript 中要正確判斷類型,當仔細去鑽研的時候,真是一件麻煩事,根據不同的情境去設計你的判斷式是相當重要的,我們也必須要去思考如何用最簡潔的方式判斷正確的類型,當然這篇還有很多地方沒有介紹到,例如 isPrototypeOf
這個方法,JavaScript 是一個有許多歷史包袱的語言,但也是不斷的在進步,運用它的時候,要注意,有太多的方式是雙面刃,切記要小心運用。
你會需要這本書:JavaScript: The Good Parts, Douglas Crockford, 2008.
其他
不少 framework 也有實作很多類型判斷的方法,下面是一例
1
|
|
怎麼做的呢
1 2 3 |
|
所以開一個這樣的 Object:
1 2 3 4 5 |
|
你就騙過他了。