// codeart.ru / Статьи / JavaScript. Грабли с NaN

JavaScript. Грабли с NaN

Автор: Evgeny Sergeev

Программируя на javascript никогда не знаешь когда встанешь на очередную граблю. Иногда складывается впечатление, что в языке больше плохого чем, хорошего.

Например, в JS есть такое значение — NaN расшифровывается как Not A Number. Обычно это значение возвращается при ошибке выполнения операций с числами.

parseInt('AAAA'); // NaN parseInt('1'); // 1 parseInt('16 somthing else'); // 16 — неожиданно, правда?

В данном примере, при выполнении первой операции функция parseInt не смогла преобразовать строку в число и поэтому вернула значения NaN. А вот в 3-ей строке, все прошло успешно, что кажется мне не совсем логичным.

Другие фокусы, которые выкидывает JavaScript хорошо демонстрирует следующий пример:

NaN == NaN; // false NaN != NaN; // true NaN > NaN; // false NaN < NaN; // false typeof NaN === 'number'// true

Получается, что NaN не равен сам себе, одновременно NaN не больше и не меньше самого себя. А если запросить его тип, то оказывается, что это число. Непонятно, почему тогда не работают операции сравнения.

Плохо в данной ситуации то, что код который многим кажется вполне рабочим, на самом деле таковым не является:

function sum(a, b) {         a = parseInt(a, 10);         b = parseInt(b, 10);         if (a == NaN || b == NaN) {                 alert('Ошибка');                 return 0;         }         return a+b; } sum('1', 'bbbb')// NaN

Причина, в том, что сравнение a == NaN || b == NaN — всегда будет возвращать false, даже если a или b будут иметь значение NaN.

Для того, чтобы узнать содержит ли переменная значение NaN используется функция isNaN:

isNaN(NaN); // true isNaN('AAAA'); // true isNaN('0'); // false

Чтобы избежать проблем со значением NaN я использую собственную функцию определения является ли переменная числом:

function isNum(v) {         return typeof v === 'number' && isFinite(v); }
  1. > Получается, что NaN не равен сам себе, одновременно NaN не больше и не меньше самого себя. А если запросить его тип, то оказывается, что это число. Непонятно, почему тогда не работают операции сравнения.

    Они, как раз, работают. А возвращают false потому что нет способа определить, что один NaN больше другого. Тут бы, конечно, следовало ошибку кинуть или вернуть null какой-нибудь. false это у них просто “дефолтное значение” как бы. Получается, что на false в сравнениях чисел нельзя ориентироваться, можно только на true.

  2. Сергей, мне кажется, что все же лучше сначала убедиться, что функция не вернуло значение NaN, а уже потом сравнивать.
    Хотя, конечно, в большинстве случаев “истина” более информативно чем “ложь”.

  3. parseInt(’16 somthing else’); // 16 — неожиданно, правда?

    А что здесь неожиданное? функция для этого и предназначена, преобразовать строку в число.
    Логика простая, берём все цифры в строке, от начала и до первого символа “не цифра”.

Leave a Reply

« Подводные камни JavaScript или опасное свойство Semicolon insertion. Как быстро проверить число на NaN »