摘要:全局屬性表示的值,顧名思義,就是表示不是一個數字。值得注意的是,是引入的,可以用上面的。而能通過函數的只有。該認為,應該返回。
這篇文章并不在我的 underscore 源碼解讀計劃中,直到 @pod4g 同學回復了我的 issue(詳見 https://github.com/hanzichi/underscore-analysis/issues/2#issuecomment-227361035)。其實之前也有同學提出 isNaN 有 native 的 function,正好借此文辨析下幾個常見的概念、方法,她們是 NaN,Number.NaN,isNaN,Number.isNaN,以及 underscore 中的 _.isNaN,順便揪出了一個 BUG。
順便安利,完整的 underscore 源碼解讀系列文章請戳 https://github.com/hanzichi/underscore-analysis
NaN & Number.NaNok,首先來了解下 NaN 和 Number.NaN 兩個屬性。
全局屬性 NaN 表示 Not-A-Number 的值,顧名思義,就是表示 不是一個數字。
在編碼中很少直接使用到 NaN。通常都是在計算失敗時,作為 Math 的某個方法的返回值出現的(例如:Math.sqrt(-1))或者嘗試將一個字符串解析成數字但失敗了的時候(例如:parseInt("blabla"))。這樣做的好處是,不會拋出錯誤,只需要在下一步的運算中判斷上個步驟的運算結果是否是 NaN 即可。
接著來看 Number.NaN,這貨和 NaN 完全一樣。其實,歸根結底這倆貨都是屬于 Number 類型:
Object.prototype.toString.call(NaN) // "[object Number]" Object.prototype.toString.call(Number.NaN) // "[object Number]"isNaN & Number.isNaN
接著來聊 isNaN 和 Number.isNaN 倆方法。
我們都知道,雖然 NaN 作為 Number 類型,但是她不等于她自己, NaN == NaN 或者 NaN === NaN 都會返回 false,那么怎么檢測一個 NaN 值呢?答案大家都知道了,isNaN 方法。
isNaN(NaN) // true isNaN(undefined) // true isNaN({}) // true isNaN("abc") // true
好多東西傳入 isNaN 的結果都是 true,并不只是 NaN,為什么?因為參數會先被強制轉換成 Number 類型,然后再進行判斷。
Number(NaN) // NaN Number(undefined) // NaN Number({}) // NaN Number("abc") // NaN
ok,強制轉換后其實都變成了 NaN。
那么 Number.isNaN 和 isNaN 有何區別呢?和全局函數 isNaN() 相比,該方法不會強制將參數轉換成數字,只有在參數是真正的數字類型,且值為 NaN 的時候才會返回 true。
isNaN = function(value) { Number.isNaN(Number(value)); } Number.isNaN = Number.isNaN || function(value) { return typeof value === "number" && isNaN(value); }
值得注意的是,Number.isNaN 是 ES6 引入的,可以用上面的 Polyfill。
_.isNaN最后來看看 underscore 對于 _.isNaN 的實現。
寫代碼首先得看需求,我們先看看 _.isNaN 的作用,查閱 API 文檔 http://underscorejs.org/#isNaN:
this is not the same as the native isNaN function, which will also return true for many other not-number values, such as undefined.
文檔指出,_.isNaN 和 native 的 isNaN 并不一樣,必須是個 Number 類型(才可能返回 true),等等,似乎和 Number.isNaN 一樣?且慢下結論。
我們來看看 edge 版本對其的實現(https://github.com/jashkenas/underscore/blob/master/underscore.js):
// Is the given value `NaN`? _.isNaN = function(obj) { return _.isNumber(obj) && isNaN(obj); };
obj 得是個 Number 類型,并且能通過 isNaN 函數的判斷,才能返回 true。其實能通過這個函數的,只有兩個值,NaN 和 new Number(NaN)(當然還有 Number.NaN,前面說了,NaN 和 Number.NaN 是一樣的東西,下同)。
而能通過 Number.isNaN 函數的只有 NaN。(Number.isNaN(new Number(NaN) 會返回 false)
但是我看的 1.8.3 其實是這樣實現的:
_.isNaN = function(obj) { return _.isNumber(obj) && obj !== +obj; };
其實這是有 BUG 的,很顯然 new Number(0) 并不應該是 Not-A-Number。
_.isNaN(new Number(0)); // true
為什么會這樣寫?這引發了我的好奇,找了下歷史記錄,是為了修復這個 issue https://github.com/jashkenas/underscore/issues/749。該 issue 認為,_.isNaN(new Number(NaN)) 應該返回 true。
我們可以看下再之前的版本對于 _.isNaN 的實現(https://github.com/jashkenas/underscore/commit/6ebb43f9b3ba88cc0cca712383534619b82f7e9b):
_.isNaN = function(obj) { return obj !== obj; };
我又翻了下當時的測試數據(https://github.com/jashkenas/underscore/blob/6ebb43f9b3ba88cc0cca712383534619b82f7e9b/test/objects.js),發現當時沒有類似 new Number(0) 的測試數據(現在已經有了)。
總結對于 NaN 的判斷,如果只針對 Number 類型,用 underscore 最新版的 _.isNaN 判斷完全沒有問題,或者用 ES6 的 Number.isNaN,兩者的區別就在于一個 new Number(NaN),不過話又說回來,沒人會這么蛋疼去這樣 new 一個 NaN 吧?
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/79737.html
摘要:返回值是一個新數組,思路也很清楚,對于已經排好序的數組,用后一個和前一個相比,不一樣就到中,對于沒有排好序的數組,要用到函數對是否包含元素進行判斷。 前面已經介紹過了,關于 _ 在內部是一個什么樣的情況,其實就是定義了一個名字叫做 _ 的函數,函數本身就是對象呀,就在 _ 上擴展了 100 多種方法。 showImg(https://segmentfault.com/img/remot...
摘要:最近開始看源碼,并將源碼解讀放在了我的計劃中。今天就跟大家聊一聊中一些常用類型檢查方法,以及一些工具類的判斷方法。用是否含有屬性來判斷工具類判斷方法接下來看下一些常用的工具類判斷方法。 Why underscore 最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計劃中。 閱讀一些著名框架類庫的源碼,就好像和一個個大師對話...
摘要:將某個列表中的元素映射到新的列表中。判斷序列中是否存在元素滿足給定方程的條件。用來查找數組中某指定元素的索引如果找不到指定的元素則返回返回指定值在字符串對象中首次出現的位置。創建一個在經過了指定計數器之后才會被調用的方程。 You dont (may not) need Lodash/Underscore Lodash 和 Underscore 是非常優秀的當代JavaScript的工...
摘要:今天要講的是,如何在數組中尋找元素,對應中的,,,以及方法。如果往一個有序數組中插入元素,使得數組繼續保持有序,那么這個插入位置是這就是這個方法的作用,有序,很顯然用二分查找即可。 Why underscore (覺得這部分眼熟的可以直接跳到下一段了...) 最近開始看 underscore.js 源碼,并將 underscore.js 源碼解讀 放在了我的 2016 計劃中。 閱讀一...
摘要:但是跟普通的是的不一樣的是,代表這一意義。的沒有的情況下,可以采用以下簡單來看,就是在原有的基礎上增加了一個的判斷,因為的是。還有一種更加簡單的實現利用了只有不跟自己相等的特性。不過我們可以通過以上方式來解釋判斷為什么會出現這樣的情況了。 例子 大家先看一看下面這個例子, isNaN(NaN); isNaN(A String); isNaN(undefined); isNaN({...
閱讀 3323·2023-04-26 00:58
閱讀 1274·2021-09-22 16:04
閱讀 3321·2021-09-02 15:11
閱讀 1566·2019-08-30 15:55
閱讀 2347·2019-08-30 15:55
閱讀 3270·2019-08-23 18:41
閱讀 3468·2019-08-23 18:18
閱讀 2759·2019-08-23 17:53