亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

ES6+ Number.isFinite()&Number.isNaN()

1. 前言

在 ES5 中,全局下的 isFinite ()isNaN () 兩種方法存在類型轉換,對最終的判斷結果存在歧義。ES6 在 Number 對象上,新提供了 Number.isFinite ()Number.isNaN () 兩個方法,更加健壯地進行數值的判斷,接下來讓我看看這兩種方法。

2. Number.isFinite()

在 ES5 中有全局的 isFinite() 函數用來判斷被傳入的參數值是否為一個有限的數值,如果參數是字符串,會首先轉為一個數值,然后在進行驗證。

isFinite(Infinity);  // false
isFinite(NaN);       // false
isFinite(-Infinity); // false

isFinite(0);         // true
isFinite(2e64);      // true
isFinite('2e64');    // true

isFinite("0");       // true

上面的代碼可以看出,字符串也會被先轉為數值再進行判斷,而 ES6 Number 對象上提供的 isFinite() 更健壯,和全局的 isFinite() 函數相比,這個方法不會強制將一個非數值的參數轉換成數值,這就意味著,只有數值類型的值,且是有窮的(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 不能通過相等操作符(== 和 ===)來判斷 ,因為 NaN == NaNNaN === NaN 都會返回 false。 因此,判斷一個值是不是 NaN 是有必要的。

3.1 NaN 值的產生

當算術運算的結果返回一個未定義的或無法表示的值時,NaN 就產生了。但是,NaN 并不一定用于表示某些值超出表示范圍的情況。

  • 將某些非數值強制轉換為數值的時候,會得到 NaN

  • 0 除以 0 會返回 NaN —— 但是其他數除以 0 則不會返回 NaN。

上一節 我們知道可以使用 Number() 方法進行類型轉換,下面列舉被強制類型轉換為 NaN 的例子:

Number(undefined)				// NaN
Number('undefined')				// NaN
Number('string')				// NaN
Number({})						// NaN
Number('10,3')					// NaN
Number('123ABC')				// NaN
Number(new Date().toString())	// NaN

上面的例子可以看出,很多值在強制類型轉換下轉為 NaN,針對這樣的值去進行判斷無疑是有問題的,下面我們來看下 isNaN () 的問題。

3.2 isNaN () 的問題

默認情況全局下存在方法 isNaN () 用了判斷是否為 NaN 值,它要求接收的是數值類型的參數,但是當參數不是 Number 類型, isNaN 函數會首先嘗試將這個參數轉換為數值,然后才會對轉換后的結果是否是 NaN 進行判斷。

實例:

isNaN(NaN);       // true
isNaN(undefined); // true
isNaN('undefined')// true
isNaN({});        // true

isNaN(true);      // false
isNaN(null);      // false
isNaN(37);        // false

// strings
isNaN("37");      // false: 可以被轉換成數值37
isNaN("37.37");   // false: 可以被轉換成數值37.37
isNaN("37,5");    // true
isNaN('123ABC');  // true:  parseInt("123ABC")的結果是 123, 但是Number("123ABC")結果是 NaN
isNaN("");        // false: 空字符串被轉換成0
isNaN(" ");       // false: 包含空格的字符串被轉換成0

// dates
isNaN(new Date());                // false
isNaN(new Date().toString());     // true

isNaN("imooc")   // true: "blabla"不能轉換成數值
                 // 轉換成數值失敗, 返回NaN

結合上面 NaN 是如何產生的例子的結果可以看出,使用 isNaN 來判斷返回的是 true,這顯然不是我們想要的結果。針對這樣的問題,ES6 做了修補,下面我們看 ES6 中的 isNaN 方法。

3.3 Number.isNaN () 詳情

ES6 提供了 Number.isNaN(x) ,通過這個方法來檢測變量 x 是否是一個 NaN 將會是一種可靠的做法,它不會對所判斷的值進行強制類型轉換。

Number.isNaN(NaN);        // true
Number.isNaN(Number.NaN); // true
Number.isNaN(0 / 0)       // true

// 下面這幾個如果使用全局的 isNaN() 時,會返回 true。
Number.isNaN("NaN");      // false,字符串 "NaN" 不會被隱式轉換成數字 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

通過上面的實例,基本覆蓋了現有程序的所有情況,不會出現使用全局下的 isNaN() 多帶來的問題。所有推薦使用 Number.isNaN(x) 方式來判斷是否是 NaN。在不支持 Number.isNaN 函數情況下,可以通過表達式 (x != x) 來檢測變量 x 是不是 NaN 會更加可靠。

4. 小結

本節中傳統的全局方法 isFinite()isNaN() 的區別在于,傳統方法先調用 Number () 將非數值的值轉為數值,再進行判斷,而這兩個新方法只對數值有效,Number.isFinite() 對于非數值一律返回 false,Number.isNaN() 只有對于 NaN 才返回 true,非 NaN 一律返回 false。