1. 程式人生 > >JavaScript中不可不知的NaN問題

JavaScript中不可不知的NaN問題

經常在javascript程式碼除錯過程中會出現一個莫名其妙的“NaN”,到底它是表示什麼呢?通過這篇文章我們來探析一下NaN的祕密。NaN,是Not a Number的縮寫, NaN 用於處理計算中出現的錯誤情況,如果參與計算的值不是一個數字,計算結果就會出現NaN。

  一些操作會導致NaN值的產生。這裡有些例子:

Math.sqrt(-2)
Math.log(-1)
0/0
parseFloat('foo')

  我們可以嘗試使用typeof來確定NaN的型別,返回結果可能是出乎你的意料的:

console.log(typeof NaN);   // 'number'

  這情情況下,NaN並不意味著是一個數字,它的型別是數字。

  保持冷靜,因為下面還有很多混亂的地方。讓我們比較兩個NaN:

var x = Math.sqrt(-2);
var y = Math.log(-1);
console.log(x == y);      // false

  也許這是因為我們沒有使用嚴格等價(===)操作?顯然不是。

var x = Math.sqrt(-2);
var y = Math.log(-1);
console.log(x === y);      // false

  好吧!難道是因為這兩個NaN是從不同的操作產生出來的?那麼這樣...

var x = Math.sqrt(-2);
var y = Math.sqrt(-2);
console.log(x == y);      // false

  再瘋狂一點

var x = Math.sqrt(-2);
console.log(x == x);      // false

  直接比較兩個NaN呢?

console.log(NaN === NaN); // false

  因為有很多方法來表示一個非數字,所以一個非數字不會等於另一個為NaN的非數字,它還是有一定道理的。不過這也是我為什麼時而崩潰的原因:

這是對你的提醒,NaN的意思是“不為NaN".
— Ariya Hidayat (@AriyaHidayat)

  不過幸運的是,在即將到來的ECMAScript 6中, 有一個Number.isNaN() 方法提供可靠的NaN值檢測。(隨便說下,你已經可以在最新版的Chrome和firefox中使用這個方法了)。在2014年4月的規範草稿中,有著如下記載:

當傳入一個數字引數並呼叫 Number.isNaN 時,會進行以下幾步:

1. 如果Type(number) 不是數字, 返回 false.
2. 如果數字是NaN, 返回true.
3. 其他情況,返回false.

  換句話說,只有在引數是真正的NaN時,才會返回true 

console.log(Number.isNaN(NaN));            // true
console.log(Number.isNaN(Math.sqrt(-2)));  // true
console.log(Number.isNaN('hello'));        // false
console.log(Number.isNaN(['x']));          // false
console.log(Number.isNaN({}));             // false
"在計算中, NaN, 代表一個非數字, 是用來呈現未定義(undefined)和不可呈現(unrepresentable)的資料型別, 尤其是在浮點計算中。"
"與NaN的比較會一直返回一個無序的結果,甚至跟它自己比較。"