Как преобразовать значение в число в JavaScript?

👨‍💻 Frontend Developer 📊 Средний 🎚️ Средний
#JavaScript #База JS

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

Преобразование в число в JavaScript можно выполнить несколькими способами:

  • Number() — универсальный конструктор
  • parseInt() — для целых чисел
  • parseFloat() — для дробных чисел
  • Унарный плюс+value
  • Математические операцииvalue * 1, value - 0

Все способы преобразования в число

МетодСинтаксисОсобенностиПример
Number()Number(value)Строгое преобразованиеNumber("123")123
parseInt()parseInt(value, radix)Парсинг целых чиселparseInt("123px")123
parseFloat()parseFloat(value)Парсинг дробных чиселparseFloat("3.14px")3.14
Унарный плюс+valueКраткая запись+"123"123
Математические операцииvalue * 1Неявное преобразование"123" * 1123

1. Конструктор Number()

Универсальный способ

// Строки с числами
console.log(Number("123")); // 123
console.log(Number("3.14")); // 3.14
console.log(Number("-42")); // -42
console.log(Number("0")); // 0
 
// Булевы значения
console.log(Number(true)); // 1
console.log(Number(false)); // 0
 
// null и undefined
console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN
 
// Пустые строки и пробелы
console.log(Number("")); // 0
console.log(Number("   ")); // 0
console.log(Number("\n\t")); // 0

Строгость Number()

// Строгое преобразование - любой лишний символ даёт NaN
console.log(Number("123px")); // NaN
console.log(Number("12.34.56")); // NaN
console.log(Number("abc")); // NaN
console.log(Number("123 456")); // NaN
 
// Но работает с научной нотацией
console.log(Number("1e3")); // 1000
console.log(Number("2.5e-2")); // 0.025
console.log(Number("Infinity")); // Infinity
console.log(Number("-Infinity")); // -Infinity

Преимущества Number()

// Безопасность с различными типами
let values = ["123", true, null, undefined, "", "   "];
values.forEach(val => {
  console.log(`${val} → ${Number(val)}`);
});
 
// Проверка на валидное число
function isValidNumber(value) {
  return !isNaN(Number(value)) && Number(value) !== Infinity;
}
 
console.log(isValidNumber("123")); // true
console.log(isValidNumber("abc")); // false
console.log(isValidNumber("")); // true (0)

2. Функция parseInt()

Парсинг целых чисел

// Базовое использование
console.log(parseInt("123")); // 123
console.log(parseInt("123.45")); // 123 (отбрасывает дробную часть)
console.log(parseInt("123px")); // 123 (игнорирует нечисловые символы)
console.log(parseInt("px123")); // NaN (должно начинаться с числа)
 
// С пробелами
console.log(parseInt("   123   ")); // 123
console.log(parseInt("\n\t123\r")); // 123
 
// Отрицательные числа
console.log(parseInt("-123")); // -123
console.log(parseInt("+123")); // 123

parseInt() с основанием системы счисления

// Различные системы счисления
console.log(parseInt("1010", 2)); // 10 (двоичная)
console.log(parseInt("777", 8)); // 511 (восьмеричная)
console.log(parseInt("ff", 16)); // 255 (шестнадцатеричная)
console.log(parseInt("zz", 36)); // 1295 (максимальное основание)
 
// Автоопределение основания (не рекомендуется)
console.log(parseInt("0x10")); // 16 (hex)
console.log(parseInt("010")); // 10 (не восьмеричная в современном JS)
 
// Практический пример
function hexToDecimal(hex) {
  return parseInt(hex.replace('#', ''), 16);
}
 
console.log(hexToDecimal('#ff0000')); // 16711680

Особенности parseInt()

// Останавливается на первом нечисловом символе
console.log(parseInt("123abc456")); // 123
console.log(parseInt("12.34.56")); // 12
console.log(parseInt("1e3")); // 1 (не понимает научную нотацию)
 
// Проблемы с дробными числами как строками
console.log(parseInt(0.0000008)); // 8 (преобразует в "8e-7")
console.log(parseInt(0.000008)); // 8
console.log(parseInt(999999999999999999999)); // 1 (большие числа)
 
// Безопасное использование
function safeParseInt(value, radix = 10) {
  if (typeof value === 'number') {
    return Math.floor(value);
  }
  return parseInt(String(value), radix);
}

3. Функция parseFloat()

Парсинг дробных чисел

// Базовое использование
console.log(parseFloat("3.14")); // 3.14
console.log(parseFloat("3.14159px")); // 3.14159
console.log(parseFloat("123")); // 123
console.log(parseFloat("123.")); // 123
 
// С пробелами
console.log(parseFloat("   3.14   ")); // 3.14
console.log(parseFloat("\n3.14\t")); // 3.14
 
// Научная нотация
console.log(parseFloat("1.23e-4")); // 0.000123
console.log(parseFloat("1.23E+2")); // 123

Особенности parseFloat()

// Останавливается на втором десятичном разделителе
console.log(parseFloat("3.14.159")); // 3.14
console.log(parseFloat("3,14")); // 3 (не понимает запятую)
 
// Infinity
console.log(parseFloat("Infinity")); // Infinity
console.log(parseFloat("-Infinity")); // -Infinity
 
// Ошибки
console.log(parseFloat("abc")); // NaN
console.log(parseFloat("")); // NaN
 
// Практическое применение
function parsePrice(priceString) {
  // "$123.45" → 123.45
  const cleaned = priceString.replace(/[^\d.-]/g, '');
  return parseFloat(cleaned) || 0;
}
 
console.log(parsePrice("$123.45")); // 123.45
console.log(parsePrice("€1,234.56")); // 1234.56

4. Унарный плюс (+)

Краткий синтаксис

// Простые случаи
console.log(+"123"); // 123
console.log(+"3.14"); // 3.14
console.log(+"-42"); // -42
console.log(+true); // 1
console.log(+false); // 0
console.log(+null); // 0
console.log(+undefined); // NaN
 
// Эквивалентно Number()
console.log(+"123" === Number("123")); // true
console.log(+"abc" === Number("abc")); // true (оба NaN)

Практическое использование

// В условиях
let userInput = "25";
if (+userInput > 18) {
  console.log("Совершеннолетний");
}
 
// В массивах
let stringNumbers = ["1", "2", "3", "4", "5"];
let numbers = stringNumbers.map(str => +str);
console.log(numbers); // [1, 2, 3, 4, 5]
 
// С датами
let timestamp = +new Date(); // текущее время в миллисекундах
console.log(timestamp);
 
// Быстрая проверка на число
function isNumeric(value) {
  return !isNaN(+value) && isFinite(+value);
}
 
console.log(isNumeric("123")); // true
console.log(isNumeric("abc")); // false

5. Математические операции

Неявное преобразование

// Умножение на 1
console.log("123" * 1); // 123
console.log("3.14" * 1); // 3.14
console.log(true * 1); // 1
console.log(false * 1); // 0
 
// Вычитание нуля
console.log("123" - 0); // 123
console.log("3.14" - 0); // 3.14
 
// Деление на 1
console.log("123" / 1); // 123
console.log("3.14" / 1); // 3.14
 
// Двойное отрицание с математической операцией
console.log(~~"123.45"); // 123 (приведение к целому)

Особенности математических операций

// Приоритет операторов
console.log("5" + 3); // "53" (конкатенация)
console.log("5" - 3); // 2 (вычитание)
console.log("5" * 3); // 15 (умножение)
console.log("5" / 3); // 1.6666666666666667 (деление)
 
// С несколькими операндами
console.log("10" - "5" + "2"); // "52" (10-5=5, затем 5+"2"="52")
console.log("10" - "5" - "2"); // 3 (все операции вычитания)
 
// Практическое применение
function calculateTotal(prices) {
  return prices.reduce((sum, price) => sum + (price * 1), 0);
}
 
let prices = ["10.50", "25.00", "5.75"];
console.log(calculateTotal(prices)); // 41.25

Сравнение методов

КритерийNumber()parseInt()parseFloat()Унарный +Math операции
СтрогостьВысокаяНизкаяНизкаяВысокаяВысокая
Дробные числа
Парсинг строкСтрогийГибкийГибкийСтрогийСтрогий
Системы счисления
ПроизводительностьСредняяВысокаяВысокаяВысокаяВысокая
Читаемость кодаОтличнаяХорошаяХорошаяСредняяНизкая

Практические задачи

Задача 1: Что выведет консоль?

console.log(Number(""));
console.log(Number("   "));
console.log(Number("0"));
console.log(Number("00"));
console.log(Number("123abc"));
Ответ

0, 0, 0, 0, NaN

Number() строго преобразует значения. Пустые строки и пробелы дают 0, любые нечисловые символы — NaN.

Задача 2: Исправьте функцию

function getAge(input) {
  return Number(input);
}
 
console.log(getAge("25")); // 25 - работает
console.log(getAge("25 лет")); // NaN - не работает!
Ответ
function getAge(input) {
  return parseInt(input, 10); // или
  // return parseFloat(input);
}
 
// Или более надёжный вариант
function getAge(input) {
  const num = parseInt(input, 10);
  return isNaN(num) ? 0 : num;
}

Используйте parseInt() для извлечения числа из строки с текстом.

Задача 3: Конвертер валют

// Нужно извлечь числовое значение из строк типа "$123.45", "€67.89"
function extractAmount(priceString) {
  // Ваш код здесь
}
 
console.log(extractAmount("$123.45")); // должно быть 123.45
console.log(extractAmount("€67.89")); // должно быть 67.89
Ответ
function extractAmount(priceString) {
  // Удаляем все символы кроме цифр, точки и минуса
  const cleaned = priceString.replace(/[^\d.-]/g, '');
  return parseFloat(cleaned) || 0;
}
 
// Альтернативный вариант с регулярным выражением
function extractAmount(priceString) {
  const match = priceString.match(/[+-]?\d+(\.\d+)?/);
  return match ? parseFloat(match[0]) : 0;
}

Задача 4: Валидация ввода

// Создайте функцию, которая проверяет, является ли строка валидным числом
function isValidNumber(input) {
  // Ваш код здесь
}
 
console.log(isValidNumber("123")); // true
console.log(isValidNumber("123.45")); // true
console.log(isValidNumber("abc")); // false
console.log(isValidNumber("")); // false
console.log(isValidNumber("Infinity")); // false
Ответ
function isValidNumber(input) {
  const num = Number(input);
  return !isNaN(num) && isFinite(num) && input.trim() !== '';
}
 
// Более строгий вариант
function isValidNumber(input) {
  return /^[+-]?\d+(\.\d+)?$/.test(input.trim());
}
 
// С поддержкой научной нотации
function isValidNumber(input) {
  return /^[+-]?\d+(\.\d+)?([eE][+-]?\d+)?$/.test(input.trim());
}

Задача 5: Оптимизация преобразования

// Какой способ быстрее для массива строк?
let stringNumbers = ["1", "2", "3", "4", "5"];
 
// Вариант A
let resultA = stringNumbers.map(str => Number(str));
 
// Вариант B
let resultB = stringNumbers.map(str => +str);
 
// Вариант C
let resultC = stringNumbers.map(str => parseInt(str, 10));
 
// Вариант D
let resultD = stringNumbers.map(str => str * 1);
Ответ

Вариант B (унарный плюс) обычно самый быстрый. Вариант D (умножение на 1) также быстрый. Вариант A (Number()) более читаемый. Вариант C (parseInt()) избыточен для простых чисел.

// Оптимальное решение
let result = stringNumbers.map(str => +str);

Продвинутые техники

Безопасное преобразование

class SafeNumber {
  static convert(value, defaultValue = 0) {
    if (value === null || value === undefined) {
      return defaultValue;
    }
    
    const num = Number(value);
    
    if (isNaN(num) || !isFinite(num)) {
      return defaultValue;
    }
    
    return num;
  }
  
  static parseInt(value, radix = 10, defaultValue = 0) {
    const num = parseInt(value, radix);
    return isNaN(num) ? defaultValue : num;
  }
  
  static parseFloat(value, defaultValue = 0) {
    const num = parseFloat(value);
    return isNaN(num) ? defaultValue : num;
  }
}
 
// Использование
console.log(SafeNumber.convert("123")); // 123
console.log(SafeNumber.convert("abc")); // 0
console.log(SafeNumber.convert("abc", -1)); // -1

Производительность и бенчмарки

// Бенчмарк разных методов
function benchmark() {
  const iterations = 1000000;
  const value = "12345";
  
  console.time('Number()');
  for (let i = 0; i < iterations; i++) {
    Number(value);
  }
  console.timeEnd('Number()');
  
  console.time('parseInt()');
  for (let i = 0; i < iterations; i++) {
    parseInt(value, 10);
  }
  console.timeEnd('parseInt()');
  
  console.time('parseFloat()');
  for (let i = 0; i < iterations; i++) {
    parseFloat(value);
  }
  console.timeEnd('parseFloat()');
  
  console.time('Unary +');
  for (let i = 0; i < iterations; i++) {
    +value;
  }
  console.timeEnd('Unary +');
  
  console.time('Math operation');
  for (let i = 0; i < iterations; i++) {
    value * 1;
  }
  console.timeEnd('Math operation');
}
 
// benchmark(); // Раскомментируйте для тестирования

Работа с большими числами

// BigInt для очень больших чисел
function convertToBigInt(value) {
  try {
    return BigInt(value);
  } catch (e) {
    console.log('Ошибка преобразования в BigInt:', e.message);
    return 0n;
  }
}
 
console.log(convertToBigInt("123456789012345678901234567890"));
 
// Проверка на безопасные целые числа
function safeInteger(value) {
  const num = Number(value);
  
  if (!Number.isSafeInteger(num)) {
    console.warn(`Число ${value} может потерять точность`);
    return convertToBigInt(value);
  }
  
  return num;
}
 
console.log(safeInteger("9007199254740991")); // безопасно
console.log(safeInteger("9007199254740992")); // предупреждение

Локализация и форматирование

// Парсинг чисел с учётом локали
function parseLocalizedNumber(value, locale = 'ru-RU') {
  // Удаляем разделители тысяч и заменяем десятичный разделитель
  if (locale === 'ru-RU') {
    // "1 234,56" → "1234.56"
    const normalized = value
      .replace(/\s/g, '') // убираем пробелы
      .replace(',', '.'); // заменяем запятую на точку
    return parseFloat(normalized);
  }
  
  if (locale === 'en-US') {
    // "1,234.56" → "1234.56"
    const normalized = value.replace(/,/g, '');
    return parseFloat(normalized);
  }
  
  return parseFloat(value);
}
 
console.log(parseLocalizedNumber("1 234,56", 'ru-RU')); // 1234.56
console.log(parseLocalizedNumber("1,234.56", 'en-US')); // 1234.56
 
// Использование Intl.NumberFormat для парсинга
function parseWithIntl(value, locale = 'ru-RU') {
  const formatter = new Intl.NumberFormat(locale);
  const parts = formatter.formatToParts(1234.56);
  
  let decimalSeparator = '.';
  let groupSeparator = ',';
  
  parts.forEach(part => {
    if (part.type === 'decimal') decimalSeparator = part.value;
    if (part.type === 'group') groupSeparator = part.value;
  });
  
  const normalized = value
    .split(groupSeparator).join('')
    .replace(decimalSeparator, '.');
    
  return parseFloat(normalized);
}

Частые ошибки и подводные камни

1. Путаница между parseInt() и Number()

// Опасно - parseInt() может дать неожиданные результаты
console.log(parseInt("08")); // 8 (хорошо)
console.log(parseInt("08", 10)); // 8 (лучше)
console.log(parseInt(0.0000008)); // 8 (плохо! преобразует в "8e-7")
 
// Безопасно
console.log(Number("08")); // 8
console.log(Number(0.0000008)); // 8e-7
 
// Правильный подход
function safeParseInt(value) {
  if (typeof value === 'number') {
    return Math.floor(value);
  }
  return parseInt(String(value), 10);
}

2. Проблемы с плавающей точкой

// Проблема точности
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(parseFloat("0.1") + parseFloat("0.2")); // 0.30000000000000004
 
// Решение
function addFloats(a, b, precision = 10) {
  return parseFloat((parseFloat(a) + parseFloat(b)).toFixed(precision));
}
 
console.log(addFloats("0.1", "0.2")); // 0.3
 
// Или используйте библиотеки типа decimal.js

3. Неожиданное поведение с пустыми значениями

// Различное поведение с пустыми значениями
console.log(Number("")); // 0
console.log(Number("   ")); // 0
console.log(parseInt("")); // NaN
console.log(parseFloat("")); // NaN
console.log(+""); // 0
 
// Безопасная проверка
function convertToNumber(value) {
  if (value === null || value === undefined || value === '') {
    return null; // или другое значение по умолчанию
  }
  
  const num = Number(value);
  return isNaN(num) ? null : num;
}

4. Проблемы с автоматическим приведением типов

// Неожиданные результаты
console.log("5" + 3); // "53" (конкатенация)
console.log("5" - 3); // 2 (вычитание)
console.log("5" * "3"); // 15 (умножение)
console.log("5" / "3"); // 1.6666666666666667 (деление)
 
// Явное преобразование для предсказуемости
function calculate(a, b, operation) {
  const numA = Number(a);
  const numB = Number(b);
  
  if (isNaN(numA) || isNaN(numB)) {
    throw new Error('Некорректные числовые значения');
  }
  
  switch (operation) {
    case '+': return numA + numB;
    case '-': return numA - numB;
    case '*': return numA * numB;
    case '/': return numA / numB;
    default: throw new Error('Неизвестная операция');
  }
}

Современные возможности

Number.isInteger() и Number.isSafeInteger()

// Проверка на целое число
console.log(Number.isInteger(123)); // true
console.log(Number.isInteger(123.0)); // true
console.log(Number.isInteger(123.45)); // false
console.log(Number.isInteger("123")); // false (строка!)
 
// Проверка на безопасное целое число
console.log(Number.isSafeInteger(123)); // true
console.log(Number.isSafeInteger(Math.pow(2, 53) - 1)); // true
console.log(Number.isSafeInteger(Math.pow(2, 53))); // false
 
// Практическое применение
function validateInteger(value) {
  const num = Number(value);
  
  if (!Number.isInteger(num)) {
    throw new Error('Значение должно быть целым числом');
  }
  
  if (!Number.isSafeInteger(num)) {
    console.warn('Число может потерять точность');
  }
  
  return num;
}

Number.parseFloat() и Number.parseInt()

// Методы объекта Number (ES6+)
console.log(Number.parseInt === parseInt); // true
console.log(Number.parseFloat === parseFloat); // true
 
// Преимущество - нет глобального загрязнения
const myParseInt = Number.parseInt;
const myParseFloat = Number.parseFloat;
 
// Использование в функциональном стиле
const stringNumbers = ["1", "2.5", "3.14", "4"];
const integers = stringNumbers.map(Number.parseInt);
const floats = stringNumbers.map(Number.parseFloat);
 
console.log(integers); // [1, 2, 3, 4]
console.log(floats); // [1, 2.5, 3.14, 4]

BigInt для больших чисел

// Работа с очень большими числами
const bigNumber = BigInt("123456789012345678901234567890");
console.log(bigNumber); // 123456789012345678901234567890n
 
// Преобразование строк в BigInt
function stringToBigInt(str) {
  try {
    return BigInt(str);
  } catch (e) {
    console.error('Ошибка преобразования в BigInt:', e.message);
    return null;
  }
}
 
// BigInt нельзя смешивать с обычными числами
try {
  console.log(bigNumber + 1); // TypeError
} catch (e) {
  console.log('Ошибка:', e.message);
}
 
// Правильно
console.log(bigNumber + 1n); // 123456789012345678901234567891n

Резюме

Преобразование в число в JavaScript — это важная операция с множеством нюансов. Важно понимать:

Number() — строгое и безопасное преобразование
parseInt() — для извлечения целых чисел из строк
parseFloat() — для извлечения дробных чисел
Унарный плюс — краткий и быстрый способ
Валидация — всегда проверяйте результат на NaN и Infinity

В современной разработке предпочитайте:

  • Number() для строгого преобразования
  • parseInt(value, 10) для извлечения целых чисел
  • parseFloat() для парсинга дробных чисел
  • Валидацию результатов с помощью isNaN() и isFinite()
  • BigInt для работы с очень большими числами

Освойте эти методы, чтобы уверенно работать с числовыми преобразованиями в любом JavaScript проекте! 🚀