昨天看到一個面試題:怎樣實現 isNaN()
方法?html
細細研究了一下 NaN
,發現這個東西不經常使用,坑卻異常多,很有 「茴」 字有幾種寫法的感受,這裏記錄下總結的東西吧。面試
NaN
是什麼NaN
即 Not a Number(非數值),但它是一個特殊的數值,因此:數組
typeof(NaN) // "number"
編碼時不多直接使用 NaN
,一般是在計算失敗時,做爲 Math
的某個方法的返回值出現的。編碼
它有兩個重要的性質:code
NaN
與任何值都不相等,包括NaN
自身:alert(NaN == NaN) // false alert(NaN === NaN) // false
NaN
的操做都會返回NaN
。NaN
?JS 在進行加減乘除運算以前,會先調用 Number()
方法,將非數值的運算項轉化爲數值,若是轉換失敗就返回NaN
,好比:htm
1-'a'; // NaN
首先是執行Number('a')
,不能成功轉化爲數值,返回NaN
,再利用NaN
的第二條性質:任何涉及 NaN
的操做都會返回NaN
,因此最終的結果是NaN
。對象
當一個值不能被Number
,parseInt
,parseFloat
成功轉換爲數值,就返回NaN
,舉例:blog
Number('123.456abc'); // NaN parseInt('123.456abc'); // 123 parseFloat('123.456abc'); // 123.456 Number('abc'); // NaN parseInt('abc'); // NaN parseFloat('abc'); // NaN Number([]); // 0 parseInt([]); // NaN parseFloat([]); // NaN Number(''); // 0 parseInt(''); // NaN parseFloat(''); // NaN Number({}); // NaN parseInt({}); // NaN parseFloat({}); // NaN
這裏要注意三者之間的差別,個人理解是 parseInt
,parseFloat
會盡可能將參數值轉化爲數值。ip
isNaN()
isNaN
是window
對象的一個方法,比較詭異的是:isNaN(x)
並非判斷參數x
自己是否是NaN
,而是判斷Number(x)
是否是NaN
。也就是說先用Number()
去轉化參數,再去判斷轉化的結果。返回的結果是一個布爾值。字符串
isNaN(NaN); // true isNaN(123); // false isNaN('abc'); //true isNaN('123abc'); //true isNaN({}); // true,由於Number({})=NaN isNaN(''); // false, 由於Number('')=0 isNaN([]); // false,由於Number([])=0
能夠看到最後, 空字符串''
和 空數組[]
顯然是非數值,而isNaN
返回了false
,緣由就是Number
轉換在做怪,這點仍是很詭異的...因此我選擇慎用...
那麼isNaN
是怎麼實現的呢,原理就是利用NaN
的第一條性質:NaN
與任何值都不相等,包括NaN
自身。
var isNaNA = function(value) { var n = Number(value); return n !== n; };
先用Number()
轉換參數,再判斷轉換後的結果是否是不等於自身。
而 MDN 上給的實現方式是這樣的:
var isNaNB = function(value) { var n = parseInt(value); return n !== n; };
我以爲是有問題的,由於:
isNaN('123abc'); // true isNaNA('123abc'); // true isNaNB('123abc'); // false
Number.isNaN()
ES6 中的Number.isNaN()
是一個判斷NaN
的升級版,和isNaN()
不一樣的是,Number.isNaN()
不會強制轉化參數,直接對參數自己作判斷,這樣只有參數顯示等於NaN
,纔會返回true
Number.isNaN(NaN); // true,其餘狀況都返回 false
它的實現原理是:
function isNaNC (value) { return typeof(value) === "number" && isNaN(value); }
算了,仍是不糾結了....