← Назад к вопросам

Какое значение у NaN в JavaScript?

1.0 Junior🔥 142 комментариев
#Node.js и JavaScript

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

NaN (Not-a-Number) в JavaScript: Полное разъяснение

NaN — одно из самых запутанных значений в JavaScript. Как backend разработчик, я часто встречаюсь с ним при парсировании данных и обработке ошибок.

Что такое NaN?

NaN расшифровывается как Not-a-Number (не число). Это специальное значение типа number, которое представляет отсутствие корректного числового значения.

typeof NaN  // 'number' — парадоксально!
console.log(NaN)  // NaN

Как появляется NaN

1. Математические операции без смысла

Math.sqrt(-1)       // NaN
0 / 0               // NaN
parseInt('hello')   // NaN
Number('abc')       // NaN

2. Нарушение типов при вычислениях

'hello' * 2         // NaN
undefined + 5       // NaN
null * 'test'       // NaN

3. Функции, вернувшие NaN

parseInt('12abc', 10)  // 12 (работает)
parseInt('abc', 10)    // NaN (не работает)

Number.parseFloat('3.14text')  // 3.14 (частично работает)
Number.parseFloat('text')      // NaN

Math.asin(2)  // NaN (значение вне диапазона [-1, 1])

Особенность: NaN !== NaN

Это самое странное свойство NaN:

NaN === NaN           // false ❌ ПАРАДОКС!
NaN == NaN            // false

// Это единственное значение в JavaScript, которое не равно самому себе

const x = NaN;
x === NaN  // false — даже переменная с NaN не равна NaN!

Почему? Потому что NaN — это не конкретное значение, а значение "неизвестности". Логично, что неизвестность не равна неизвестности.

Как проверить на NaN

1. Правильный способ: Number.isNaN()

Number.isNaN(NaN)      // true ✅
Number.isNaN(10)       // false
Number.isNaN('hello')  // false
Number.isNaN(undefined) // false

Это строгая проверка: работает только для самого NaN.

2. Старый способ: isNaN() (НЕ рекомендуется)

isNaN(NaN)        // true
isNaN(10)         // false
isNaN('hello')    // true  ⚠️ НЕОЖИДАННО!
isNaN(undefined)  // true  ⚠️ НЕОЖИДАННО!

// isNaN() преобразует значение в число ДО проверки
// Это неправильное поведение

3. Проверка через Object.is() (ES6)

Object.is(NaN, NaN)   // true ✅
Object.is(10, NaN)    // false
Object.is(0, -0)      // false (но это другая история)

Работа с NaN в коде

Парсинг чисел с обработкой ошибок:

function parseNumber(value) {
  const num = Number(value);
  
  if (Number.isNaN(num)) {
    throw new Error(`Invalid number: ${value}`);
  }
  
  return num;
}

parseNumber('42')      // 42
parseNumber('hello')   // Error: Invalid number: hello

API запрос с валидацией:

app.get('/api/calculate', (req, res) => {
  const { a, b } = req.query;
  
  const numA = Number(a);
  const numB = Number(b);
  
  // Проверка валидности
  if (Number.isNaN(numA) || Number.isNaN(numB)) {
    return res.status(400).json({ 
      error: 'Invalid number parameters',
      a: isNaN(numA) ? 'invalid' : 'valid',
      b: isNaN(numB) ? 'invalid' : 'valid'
    });
  }
  
  const result = numA + numB;
  res.json({ result });
});

Обработка результатов JSON:

const data = JSON.parse('{"value": NaN}'); // ⚠️ SyntaxError!
// JSON не поддерживает NaN

// Вместо этого используй null или строку
const data = JSON.parse('{"value": null}'); // ✅

// При сериализации NaN становится null
JSON.stringify({ value: NaN })  // '{"value":null}'

Арифметика с NaN

NaN распространяется как чума:

NaN + 5       // NaN
NaN * 2       // NaN
10 / NaN      // NaN
Math.pow(NaN, 2)  // NaN

// Единственный способ избежать NaN в цепи — проверить!
const value = parseFloat(input);
const result = Number.isNaN(value) ? 0 : value + 10;

Сравнения с NaN

NaN > 10      // false
NaN < 10      // false
NaN >= 10     // false
NaN <= 10     // false

// Все сравнения с NaN возвращают false!

Фильтрация массива от NaN:

const numbers = [1, NaN, 3, NaN, 5];

// Метод 1
const filtered = numbers.filter(n => Number.isNaN(n) === false);
// [1, 3, 5]

// Метод 2
const filtered = numbers.filter(n => !Number.isNaN(n));
// [1, 3, 5]

// Метод 3 — используй Object.is()
const filtered = numbers.filter(n => !Object.is(n, NaN));
// [1, 3, 5]

Практический пример: обработка API ответа

class DataProcessor {
  processMetrics(data) {
    const metrics = {
      average: NaN,
      sum: 0,
      count: 0
    };
    
    const validValues = data.values
      .map(v => Number(v))
      .filter(v => Number.isNaN(v) === false);
    
    if (validValues.length === 0) {
      return {
        success: false,
        error: 'No valid numbers found',
        metrics
      };
    }
    
    const sum = validValues.reduce((a, b) => a + b, 0);
    const average = sum / validValues.length;
    
    return {
      success: true,
      metrics: {
        average,
        sum,
        count: validValues.length
      }
    };
  }
}

NaN в логировании

const logger = require('winston');

const invalidValue = parseFloat('invalid');

// ❌ Проблема: JSON.stringify(NaN) → null
logger.info('Value:', { value: invalidValue });
// Записывает: {"value": null} — потеря информации!

// ✅ Правильно: проверь перед логированием
if (Number.isNaN(invalidValue)) {
  logger.warn('Invalid value detected', { value: 'NaN' });
} else {
  logger.info('Value processed', { value: invalidValue });
}

Итого: ключевые моменты

  1. NaN это число типа: typeof NaN === 'number'
  2. NaN !== NaN: единственное значение, не равное себе
  3. Используй Number.isNaN(): для проверки (не isNaN!)
  4. NaN заразно: любая операция с NaN дает NaN
  5. JSON не поддерживает NaN: будет null
  6. Всегда валидируй парсированные числа: перед использованием

В production коде: всегда проверяй результаты парсинга и математических операций, чтобы избежать скрытых NaN ошибок.