Какое значение у NaN в JavaScript?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
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 });
}
Итого: ключевые моменты
- NaN это число типа:
typeof NaN === 'number' - NaN !== NaN: единственное значение, не равное себе
- Используй Number.isNaN(): для проверки (не isNaN!)
- NaN заразно: любая операция с NaN дает NaN
- JSON не поддерживает NaN: будет null
- Всегда валидируй парсированные числа: перед использованием
В production коде: всегда проверяй результаты парсинга и математических операций, чтобы избежать скрытых NaN ошибок.