ES6+ Number.isFinite()&Number.isNaN()
1. 前言
在 ES5 中,全局下的 isFinite ()
和 isNaN ()
兩種方法存在類型轉(zhuǎn)換,對(duì)最終的判斷結(jié)果存在歧義。ES6 在 Number 對(duì)象上,新提供了 Number.isFinite ()
和 Number.isNaN ()
兩個(gè)方法,更加健壯地進(jìn)行數(shù)值的判斷,接下來讓我看看這兩種方法。
2. Number.isFinite()
在 ES5 中有全局的 isFinite()
函數(shù)用來判斷被傳入的參數(shù)值是否為一個(gè)有限的數(shù)值,如果參數(shù)是字符串,會(huì)首先轉(zhuǎn)為一個(gè)數(shù)值,然后在進(jìn)行驗(yàn)證。
isFinite(Infinity); // false
isFinite(NaN); // false
isFinite(-Infinity); // false
isFinite(0); // true
isFinite(2e64); // true
isFinite('2e64'); // true
isFinite("0"); // true
上面的代碼可以看出,字符串也會(huì)被先轉(zhuǎn)為數(shù)值再進(jìn)行判斷,而 ES6 Number 對(duì)象上提供的 isFinite()
更健壯,和全局的 isFinite()
函數(shù)相比,這個(gè)方法不會(huì)強(qiáng)制將一個(gè)非數(shù)值的參數(shù)轉(zhuǎn)換成數(shù)值,這就意味著,只有數(shù)值類型的值,且是有窮的(finite),才返回 true
。
Number.isFinite(Infinity); // false
Number.isFinite(NaN); // false
Number.isFinite(-Infinity); // false
Number.isFinite(0); // true
Number.isFinite(2e64); // true
Number.isFinite('2e64'); // false
Number.isFinite('0'); // false
3. Number.isNaN()
在 JavaScript 中與其它的值不同,NaN
不能通過相等操作符(== 和 ===)來判斷 ,因?yàn)?NaN == NaN
和 NaN === NaN
都會(huì)返回 false
。 因此,判斷一個(gè)值是不是 NaN
是有必要的。
3.1 NaN 值的產(chǎn)生
當(dāng)算術(shù)運(yùn)算的結(jié)果返回一個(gè)未定義的或無法表示的值時(shí),NaN
就產(chǎn)生了。但是,NaN
并不一定用于表示某些值超出表示范圍的情況。
-
將某些非數(shù)值強(qiáng)制轉(zhuǎn)換為數(shù)值的時(shí)候,會(huì)得到
NaN
。 -
0 除以 0 會(huì)返回 NaN —— 但是其他數(shù)除以 0 則不會(huì)返回 NaN。
上一節(jié) 我們知道可以使用 Number()
方法進(jìn)行類型轉(zhuǎn)換,下面列舉被強(qiáng)制類型轉(zhuǎn)換為 NaN
的例子:
Number(undefined) // NaN
Number('undefined') // NaN
Number('string') // NaN
Number({}) // NaN
Number('10,3') // NaN
Number('123ABC') // NaN
Number(new Date().toString()) // NaN
上面的例子可以看出,很多值在強(qiáng)制類型轉(zhuǎn)換下轉(zhuǎn)為 NaN
,針對(duì)這樣的值去進(jìn)行判斷無疑是有問題的,下面我們來看下 isNaN ()
的問題。
3.2 isNaN () 的問題
默認(rèn)情況全局下存在方法 isNaN ()
用了判斷是否為 NaN
值,它要求接收的是數(shù)值類型的參數(shù),但是當(dāng)參數(shù)不是 Number
類型, isNaN
函數(shù)會(huì)首先嘗試將這個(gè)參數(shù)轉(zhuǎn)換為數(shù)值,然后才會(huì)對(duì)轉(zhuǎn)換后的結(jié)果是否是 NaN
進(jìn)行判斷。
實(shí)例:
isNaN(NaN); // true
isNaN(undefined); // true
isNaN('undefined')// true
isNaN({}); // true
isNaN(true); // false
isNaN(null); // false
isNaN(37); // false
// strings
isNaN("37"); // false: 可以被轉(zhuǎn)換成數(shù)值37
isNaN("37.37"); // false: 可以被轉(zhuǎn)換成數(shù)值37.37
isNaN("37,5"); // true
isNaN('123ABC'); // true: parseInt("123ABC")的結(jié)果是 123, 但是Number("123ABC")結(jié)果是 NaN
isNaN(""); // false: 空字符串被轉(zhuǎn)換成0
isNaN(" "); // false: 包含空格的字符串被轉(zhuǎn)換成0
// dates
isNaN(new Date()); // false
isNaN(new Date().toString()); // true
isNaN("imooc") // true: "blabla"不能轉(zhuǎn)換成數(shù)值
// 轉(zhuǎn)換成數(shù)值失敗, 返回NaN
結(jié)合上面 NaN 是如何產(chǎn)生的例子的結(jié)果可以看出,使用 isNaN
來判斷返回的是 true
,這顯然不是我們想要的結(jié)果。針對(duì)這樣的問題,ES6 做了修補(bǔ),下面我們看 ES6 中的 isNaN
方法。
3.3 Number.isNaN () 詳情
ES6 提供了 Number.isNaN(x)
,通過這個(gè)方法來檢測變量 x
是否是一個(gè) NaN
將會(huì)是一種可靠的做法,它不會(huì)對(duì)所判斷的值進(jìn)行強(qiáng)制類型轉(zhuǎn)換。
Number.isNaN(NaN); // true
Number.isNaN(Number.NaN); // true
Number.isNaN(0 / 0) // true
// 下面這幾個(gè)如果使用全局的 isNaN() 時(shí),會(huì)返回 true。
Number.isNaN("NaN"); // false,字符串 "NaN" 不會(huì)被隱式轉(zhuǎn)換成數(shù)字 NaN。
Number.isNaN(undefined); // false
Number.isNaN('undefined');// false
Number.isNaN({}); // false
Number.isNaN("blabla"); // false
Number.isNaN(true); // false
Number.isNaN(null); // false
Number.isNaN(37); // false
Number.isNaN("37"); // false
Number.isNaN("37.37"); // false
Number.isNaN(""); // false
Number.isNaN(" "); // false
通過上面的實(shí)例,基本覆蓋了現(xiàn)有程序的所有情況,不會(huì)出現(xiàn)使用全局下的 isNaN()
多帶來的問題。所有推薦使用 Number.isNaN(x)
方式來判斷是否是 NaN
。在不支持 Number.isNaN
函數(shù)情況下,可以通過表達(dá)式 (x != x)
來檢測變量 x
是不是 NaN
會(huì)更加可靠。
4. 小結(jié)
本節(jié)中傳統(tǒng)的全局方法 isFinite()
和 isNaN()
的區(qū)別在于,傳統(tǒng)方法先調(diào)用 Number () 將非數(shù)值的值轉(zhuǎn)為數(shù)值,再進(jìn)行判斷,而這兩個(gè)新方法只對(duì)數(shù)值有效,Number.isFinite()
對(duì)于非數(shù)值一律返回 false,Number.isNaN()
只有對(duì)于 NaN
才返回 true
,非 NaN
一律返回 false
。