← JavaScript/Преобразование типов#65 из 383← ПредыдущийСледующий →+20 XP
Полезно по теме:Гайд: как учить JavaScriptПрактика: JS базаПрактика: async и сетьТермин: Closure

Преобразование типов

Реальная проблема: форма на сайте

Пользователь вводит цену товара в поле ввода — и браузер отдаёт вам строку "1500". Если вы напишете price + shipping, получите "1500200" вместо 1700. Это не баг браузера — это поведение JavaScript. Понимание преобразования типов спасёт вас от таких сюрпризов.

Что такое преобразование типов

JavaScript умеет автоматически менять тип значения в зависимости от контекста — это называется неявным преобразованием. Но полагаться на него опасно. Лучше делать это явно — тогда код предсказуем.

На основе предыдущих уроков

  • «Типы данных» — примитивы: string, number, boolean, null, undefined
  • «Сравнения» — почему '5' == 5 это true (неявное приведение)
  • «Функции» — функции Number(), String(), Boolean()
  • Явное преобразование

    // В число
    Number('42')       // 42
    Number('3.14')     // 3.14
    Number('')         // 0
    Number('hello')    // NaN — не число
    Number(true)       // 1
    Number(false)      // 0
    Number(null)       // 0
    Number(undefined)  // NaN
    
    // В строку
    String(42)         // '42'
    String(true)       // 'true'
    String(null)       // 'null'
    String(undefined)  // 'undefined'
    
    // В boolean — запомни что «ложно»:
    Boolean(0)         // false
    Boolean('')        // false
    Boolean(null)      // false
    Boolean(undefined) // false
    Boolean(NaN)       // false
    // Всё остальное — true, включая '0' и []!
    Boolean('0')       // true
    Boolean([])        // true

    parseInt и parseFloat

    Эти функции «читают» число из начала строки и останавливаются при первом нечисловом символе:

    parseInt('42px')     // 42 — берёт число, игнорирует 'px'
    parseFloat('3.14$')  // 3.14
    parseInt('$42')      // NaN — строка начинается не с числа
    parseInt('10', 2)    // 2 — парсинг в двоичной системе

    Неявное преобразование — ловушки

    '5' + 3      // '53'  — + с строкой = конкатенация
    '5' - 3      // 2     — - всегда числовой
    '5' * '3'    // 15    — * приводит оба к числу
    true + 1     // 2     — true → 1
    null + 1     // 1     — null → 0
    undefined + 1 // NaN  — undefined → NaN
    [] + {}      // '[object Object]' — сюрприз!

    Типичные ошибки

    Ошибка 1: сложение вместо суммирования

    // Сломано: input.value всегда строка
    const price = document.querySelector('#price').value  // '1500'
    const tax = 200
    console.log(price + tax)  // '1500200' — конкатенация!
    
    // Исправлено:
    console.log(Number(price) + tax)  // 1700

    Ошибка 2: toFixed возвращает строку

    // Сломано:
    const result = (1.005).toFixed(2)  // '1.01' — это строка!
    console.log(result + 1)  // '1.011' — снова конкатенация
    
    // Исправлено:
    console.log(+(1.005).toFixed(2) + 1)  // 2.01

    Ошибка 3: isNaN с нечисловыми аргументами

    // Сломано:
    isNaN('hello')   // true — но сначала 'hello' → NaN, потом проверка
    isNaN(undefined) // true — undefined → NaN
    
    // Лучше использовать Number.isNaN — строгая проверка:
    Number.isNaN('hello')   // false — не NaN, это строка
    Number.isNaN(NaN)       // true — именно NaN

    В реальных проектах

  • Форма оплаты: Number(input.value) перед арифметикой
  • API-ответ: числа в JSON приходят как числа, но query-параметры URL — всегда строки: Number(new URLSearchParams(location.search).get('page'))
  • localStorage: всё хранится как строка, при чтении нужен парсинг
  • Флаги: Boolean(user.isAdmin) или просто !!user.isAdmin
  • Примеры

    Обработка данных формы интернет-магазина

    // Симуляция данных из формы (всё приходит строками)
    const formData = {
      price: '1499',
      quantity: '3',
      discount: '10',
      promoCode: '',
    }
    
    // Неверно — получим конкатенацию строк
    console.log(formData.price + formData.quantity)  // '14993' — не 1502!
    
    // Верно — явное преобразование
    const price    = Number(formData.price)     // 1499
    const quantity = Number(formData.quantity)  // 3
    const discount = Number(formData.discount)  // 10
    
    const subtotal   = price * quantity          // 4497
    const discounted = subtotal * (1 - discount / 100)
    console.log(discounted)  // 4047.3
    
    // Пустая строка promo → false
    const hasPromo = Boolean(formData.promoCode)
    console.log(hasPromo)  // false
    
    // Безопасная функция парсинга цены (поддержка '1 499,99' и '1499.99')
    function parsePrice(str) {
      const cleaned = str.replace(/\s/g, '').replace(',', '.')
      const num = Number(cleaned)
      return Number.isNaN(num) ? null : num
    }
    
    console.log(parsePrice('1 499,99'))  // 1499.99
    console.log(parsePrice('75000'))     // 75000
    console.log(parsePrice('abc'))       // null

    Преобразование типов

    Реальная проблема: форма на сайте

    Пользователь вводит цену товара в поле ввода — и браузер отдаёт вам строку "1500". Если вы напишете price + shipping, получите "1500200" вместо 1700. Это не баг браузера — это поведение JavaScript. Понимание преобразования типов спасёт вас от таких сюрпризов.

    Что такое преобразование типов

    JavaScript умеет автоматически менять тип значения в зависимости от контекста — это называется неявным преобразованием. Но полагаться на него опасно. Лучше делать это явно — тогда код предсказуем.

    На основе предыдущих уроков

  • «Типы данных» — примитивы: string, number, boolean, null, undefined
  • «Сравнения» — почему '5' == 5 это true (неявное приведение)
  • «Функции» — функции Number(), String(), Boolean()
  • Явное преобразование

    // В число
    Number('42')       // 42
    Number('3.14')     // 3.14
    Number('')         // 0
    Number('hello')    // NaN — не число
    Number(true)       // 1
    Number(false)      // 0
    Number(null)       // 0
    Number(undefined)  // NaN
    
    // В строку
    String(42)         // '42'
    String(true)       // 'true'
    String(null)       // 'null'
    String(undefined)  // 'undefined'
    
    // В boolean — запомни что «ложно»:
    Boolean(0)         // false
    Boolean('')        // false
    Boolean(null)      // false
    Boolean(undefined) // false
    Boolean(NaN)       // false
    // Всё остальное — true, включая '0' и []!
    Boolean('0')       // true
    Boolean([])        // true

    parseInt и parseFloat

    Эти функции «читают» число из начала строки и останавливаются при первом нечисловом символе:

    parseInt('42px')     // 42 — берёт число, игнорирует 'px'
    parseFloat('3.14$')  // 3.14
    parseInt('$42')      // NaN — строка начинается не с числа
    parseInt('10', 2)    // 2 — парсинг в двоичной системе

    Неявное преобразование — ловушки

    '5' + 3      // '53'  — + с строкой = конкатенация
    '5' - 3      // 2     — - всегда числовой
    '5' * '3'    // 15    — * приводит оба к числу
    true + 1     // 2     — true → 1
    null + 1     // 1     — null → 0
    undefined + 1 // NaN  — undefined → NaN
    [] + {}      // '[object Object]' — сюрприз!

    Типичные ошибки

    Ошибка 1: сложение вместо суммирования

    // Сломано: input.value всегда строка
    const price = document.querySelector('#price').value  // '1500'
    const tax = 200
    console.log(price + tax)  // '1500200' — конкатенация!
    
    // Исправлено:
    console.log(Number(price) + tax)  // 1700

    Ошибка 2: toFixed возвращает строку

    // Сломано:
    const result = (1.005).toFixed(2)  // '1.01' — это строка!
    console.log(result + 1)  // '1.011' — снова конкатенация
    
    // Исправлено:
    console.log(+(1.005).toFixed(2) + 1)  // 2.01

    Ошибка 3: isNaN с нечисловыми аргументами

    // Сломано:
    isNaN('hello')   // true — но сначала 'hello' → NaN, потом проверка
    isNaN(undefined) // true — undefined → NaN
    
    // Лучше использовать Number.isNaN — строгая проверка:
    Number.isNaN('hello')   // false — не NaN, это строка
    Number.isNaN(NaN)       // true — именно NaN

    В реальных проектах

  • Форма оплаты: Number(input.value) перед арифметикой
  • API-ответ: числа в JSON приходят как числа, но query-параметры URL — всегда строки: Number(new URLSearchParams(location.search).get('page'))
  • localStorage: всё хранится как строка, при чтении нужен парсинг
  • Флаги: Boolean(user.isAdmin) или просто !!user.isAdmin
  • Примеры

    Обработка данных формы интернет-магазина

    // Симуляция данных из формы (всё приходит строками)
    const formData = {
      price: '1499',
      quantity: '3',
      discount: '10',
      promoCode: '',
    }
    
    // Неверно — получим конкатенацию строк
    console.log(formData.price + formData.quantity)  // '14993' — не 1502!
    
    // Верно — явное преобразование
    const price    = Number(formData.price)     // 1499
    const quantity = Number(formData.quantity)  // 3
    const discount = Number(formData.discount)  // 10
    
    const subtotal   = price * quantity          // 4497
    const discounted = subtotal * (1 - discount / 100)
    console.log(discounted)  // 4047.3
    
    // Пустая строка promo → false
    const hasPromo = Boolean(formData.promoCode)
    console.log(hasPromo)  // false
    
    // Безопасная функция парсинга цены (поддержка '1 499,99' и '1499.99')
    function parsePrice(str) {
      const cleaned = str.replace(/\s/g, '').replace(',', '.')
      const num = Number(cleaned)
      return Number.isNaN(num) ? null : num
    }
    
    console.log(parsePrice('1 499,99'))  // 1499.99
    console.log(parsePrice('75000'))     // 75000
    console.log(parsePrice('abc'))       // null

    Задание

    Интернет-магазин получает данные из URL: `?price=1500&qty=3&vat=20`. Все значения — строки. Напиши функцию calcTotal(params), которая принимает объект с этими строками и возвращает итоговую сумму с НДС. Если любой параметр не является числом — верни null.

    Подсказка

    Используй Number() для каждого параметра. Для проверки — Number.isNaN(price) || Number.isNaN(qty) || Number.isNaN(vat). Итого: price * qty * (1 + vat / 100)

    Загружаем среду выполнения...
    Загружаем AI-помощника...