Как вы тестируете NaN в JavaScript?

У меня есть переменная x, и я хочу проверить, установлен ли x на NaN. Как это сделать?

Мой первый инстинкт, вероятно, должен проверить, как это:

if (x === NaN) {  ...

Глупый кролик, нет, это было бы слишком легко. NaN как NULL в SQL, он не равен ничему, даже самому себе.

Но посмотрите, есть функция, называемая isNaN() - возможно, это сделает это!

Нет, насколько я могу судить, isNaN() совершенно бесполезен.

Например, isNaN([""]) корректно возвращает false, но isNaN(["."]) возвращает true. Вы не хотите знать, как я узнал об этом недостатке.

Как это сделать?

Оказывается, мой вопрос является дубликатом этого, но выбранный ответ неверен. Правильный ответ имеет на 20% больше голосов.

Ответ 1

У вопроса есть ответ, если вы прочтете достаточно внимательно. Так я его нашел: я печатал вопрос и... бинго.

Помнишь, когда я писал: "NaN как NULL в SQL, он ничем не равен, даже самому себе"? Насколько я знаю, NaN - единственное значение в Javascript с этим свойством. Поэтому вы можете написать:

var reallyIsNaN = function(x) {
   return x !== x;
};

Ответ 2

Короткий ответ

Для пользователей ECMAScript-5:

#1
if(x !== x) {
    console.info('x is NaN.');
}
else {
    console.info('x is NOT a NaN.');
}

Для людей, использующих ECMAScript-6:

#2
Number.isNaN(x);

И для целей согласованности в ECMAScript 5 и 6 вы также можете использовать этот polyfill для Number.isNan

#3
//Polyfill from MDN
Number.isNaN = Number.isNaN || function(value) {
    return typeof value === "number" && isNaN(value);
}
// Or
Number.isNaN = Number.isNaN || function(value) {     
    return value !== value;
}

Примечание. Я предпочитаю тестировать, используя # 1, который работает одинаково во всех местах и ​​не имеет зависимости от последнего JS. (Это всегда дает мне правильный результат. Никаких сюрпризов!)


Подробное объяснение:

Вот наш удивительный NaN

NaN == NaN; // false
NaN === NaN; // false

Пожалуйста, не обвиняйте JavaScript для этого, это NaN, который должен вести себя таким же образом на других языках, что также прекрасно по обоснованию для всех сравнений, возвращающих ложные NaN значения

Таким образом, мы получаем isNaN как наш спаситель, но ждите, что он действует немного по-другому в некоторых сценариях, таких как

isNaN(undefined); // true
isNaN({});        // true
isNaN("lorem ipsum"); // true

У меня были некоторые странные лица, увидев результаты выше. И вот причина из MDN

Когда аргумент функции isNaN не имеет тип Number, значение сначала принудительно вводится в число. Полученное значение затем проверяется, чтобы определить, является ли это NaN.

Итак, как мы должны тестировать NaN для переменных без чисел? Я всегда придерживаюсь следующих

if(x !== x) {
    console.info('Is a NaN');
}
else {
    console.info('Not a NaN');
}

Обновления ECMAScript-6/JavaScript-2015

У нас есть что-то в ECMAScript-6 для того же. Да, мы делаем...

Number.isNaN(x); // true

Реализация ES6 также будет полезна для вышеуказанных случаев, таких как

Number.isNaN(undefined); // false
Number.isNaN({}); // false    
Number.isNaN("lorem ipsum"); // false

тогда как глобальная функция ECMAScript-5 isNaN выводит в true для вышеуказанных случаев, что иногда может не совпадать с нашим ожиданием.