JavaScript中NaN的祕密

ourjs發表於2014-05-27

  NaN,不是一個數字,是一種特殊的值來代表不可表示的值,使用typeof或其他任何與之比較的處理方式,‘NaN’則會引起一些混亂,

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

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

  對於很多JavaScript的初學者來說,它的第一個陷阱是呼叫typeof時返回結果的通常是你想不到的:

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 7提交該方案的

GarlicNaN != NaN

  但是當然,解決方案現在已經有了。

  讓我們認識一下全域性函式isNaN:

console.log(isNaN(NaN));      // true

  唉,不過 isNaN() 也有它自己的很多缺陷呀:

console.log(isNaN('hello'));  // true
console.log(isNaN(['x']));    // true
console.log(isNaN({}));       // true

  這樣又產生 了很多不同的解決方案。其中一個是利用 了NaN的非反射性質(例如, 看看 Kit Cambridge 的筆記)

var My = {
  isNaN: function (x) { return x !== x; }
}

  另外一個例子是先檢查值的型別(防止強制轉換):

My.isNaN = function(x) { return typeof x === 'number' && isNaN(x)};

  不過幸運的是,在即將到來的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時,要格外小心了。

  附: Poetro 的評論

  這是 IEEE 754 定義的NaN標準, 跟JavaScript無關。

"在計算中, NaN, 代表一個非數字, 是用來呈現未定義(undefined)和不可呈現(unrepresentable)的資料型別, 尤其是在浮點計算中。"
"與NaN的比較會一直返回一個無序的結果,甚至跟它自己比較。"

  原文 ariya.ofilabs.com

相關文章