深入理解 NaN 與 isNaN 方法

一、NaN
NaN,即 not a number,從字面意思上可以理解爲非數字,但是在 JavaScript 的數據類型劃分的時候,我們還是將其劃分進 number 類型:

typeof NaN; // “number”
實際上,它是在算術運算過程中,在原本期望得到一個數字類型數據的地方,卻沒有辦法得出數字類型的結果的時候,其它類型編程語言可能將拋出異常,而 JavaScript 將得到一個 NaN:

1 - ‘a’; // NaN
1 / ‘a’; // NaN
1 - {}; // NaN
1 + NaN; // NaN
1 * {}; // NaN
但需要注意一些特殊情況:

JavaScript 中,+ 既是加法運算符,又是字符串連接符(當操作數中含有字符串時,認爲是字符串連接操作)
1 + ‘a’; // ‘1a’
‘1’ + 1; // ‘11’
當分母爲 0 的時候,將得到特殊的 Infinity 和 - Infinity
1 / 0; // Infinity
1 / (-0); // -Infinity
操作數可能被隱式轉換
1 + {}; // “1[object Object]”

1 + new Date(‘2019-09-01’);
// “1Sun Sep 01 2019 08:00:00 GMT+0800 (中國標準時間)”

1 + [1, 2]; // ‘11,2’

二 、判斷是否爲 NaN
在 JavaScript NaN 有一個其它類型數據都不具備的特性,這個數據與它本身不相等:

NaN == NaN; // false
NaN === NaN; // false
所以,我們可以基於這一點,來判斷一個數據是否是 NaN:

function ifNaN(data) {
return data !== data;
}
ifNaN(NaN); // true
ifNaN(1); // false
三、原生的 isNaN 方法
第一感覺,isNaN 方法應該和我們前面實現的 ifNaN 效果一樣,但實際上二者區別卻很大:

isNaN(null); // false
isNaN(undefined); // true
isNaN(1); // false
isNaN({}); // true
isNaN(‘123’); // false
isNaN(‘0xa’); // false
isNaN 的定位跟之前的 ifNaN 不太一樣,ifNaN 是確定一個數據是否是 NaN,是 NaN 就返回 true,否則返回 false;isNaN 是確定一個數據在與其它數字類型數據進行算術運算之後,是否可能得出 NaN:

null - 1; // -1
undefined - 1; // NaN
1 - 1; // 0
{} - 1; // NaN
‘123’ - 1; // 121
‘0xa’ - 1; // 9
這一點上,其實與上面 isNaN 的行爲保持一致了。
在調用 isNaN 時,如果傳入的參數不是 number 類型,則會嘗試隱式轉換成 number 類型的數據,所以, isNaN(xxx) 其實與 isNaN(Nunber(xxx)) 等價,所以上面 isNaN 的行爲也就解釋得通了。

注:最初版本的 isNaN 是定義在全局對象 window(瀏覽器環境) / global(nodejs) 對象上的,但是 ES6 在 Number 構造函數上添加了一個靜態方法 Number.isNaN,其效果與之前的 ifNaN 保持一致了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章