一还惠、NaN
NaN,即 not a number,從字面意思上可以理解為非數(shù)字冲茸,但是在 JavaScript 的數(shù)據(jù)類型劃分的時候,我們還是將其劃分進 number 類型:
typeof NaN; // "number"
實際上缅帘,它是在算術(shù)運算過程中轴术,在原本期望得到一個數(shù)字類型數(shù)據(jù)的地方,卻沒有辦法得出數(shù)字類型的結(jié)果的時候钦无,其它類型編程語言可能將拋出異常逗栽,而 JavaScript 將得到一個 NaN:
1 - 'a'; // NaN
1 / 'a'; // NaN
1 - {}; // NaN
1 + NaN; // NaN
1 * {}; // NaN
但需要注意一些特殊情況:
- JavaScript 中,+ 既是加法運算符失暂,又是字符串連接符(當操作數(shù)中含有字符串時彼宠,認為是字符串連接操作)
1 + 'a'; // '1a'
'1' + 1; // '11'
- 當分母為 0 的時候,將得到特殊的 Infinity 和 - Infinity
1 / 0; // Infinity
1 / (-0); // -Infinity
- 操作數(shù)可能被隱式轉(zhuǎn)換
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 有一個其它類型數(shù)據(jù)都不具備的特性凭峡,這個數(shù)據(jù)與它本身不相等:
NaN == NaN; // false
NaN === NaN; // false
所以,我們可以基于這一點决记,來判斷一個數(shù)據(jù)是否是 NaN:
function ifNaN(data) {
return data !== data;
}
ifNaN(NaN); // true
ifNaN(1); // false
三摧冀、原生的 isNaN 方法
第一感覺,isNaN 方法應該和我們前面實現(xiàn)的 ifNaN 效果一樣,但實際上二者區(qū)別卻很大:
isNaN(null); // false
isNaN(undefined); // true
isNaN(1); // false
isNaN({}); // true
isNaN('123'); // false
isNaN('0xa'); // false
isNaN 的定位跟之前的 ifNaN 不太一樣索昂,ifNaN 是確定一個數(shù)據(jù)是否是 NaN建车,是 NaN 就返回 true,否則返回 false椒惨;isNaN 是確定一個數(shù)據(jù)在與其它數(shù)字類型數(shù)據(jù)進行算術(shù)運算之后癞志,是否可能得出 NaN:
null - 1; // -1
undefined - 1; // NaN
1 - 1; // 0
{} - 1; // NaN
'123' - 1; // 121
'0xa' - 1; // 9
這一點上,其實與上面 isNaN 的行為保持一致了框产。
在調(diào)用 isNaN 時凄杯,如果傳入的參數(shù)不是 number 類型,則會嘗試隱式轉(zhuǎn)換成 number 類型的數(shù)據(jù)秉宿,所以戒突, isNaN(xxx) 其實與 isNaN(Nunber(xxx)) 等價,所以上面 isNaN 的行為也就解釋得通了描睦。
注:最初版本的 isNaN 是定義在全局對象 window(瀏覽器環(huán)境) / global(nodejs) 對象上的膊存,但是 ES6 在 Number 構(gòu)造函數(shù)上添加了一個靜態(tài)方法 Number.isNaN,其效果與之前的 ifNaN 保持一致了忱叭。