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