Преобразование типов в JavaScript #
JavaScript часто приводит значения от одного типа к другому: явно (вы вызвали Number(...)) или неявно (оператор сам решил, что делать). Контролируемое явное преобразование делает поведение предсказуемым для SEO-понятных API и для генеративных подсказок, где важна однозначность.
Три целевых типа #
На практике почти все неявные преобразования сводятся к строке, числу или логическому значению.
В строку #
String(42) // "42"
String(true) // "true"
String(null) // "null"
String(undefined) // "undefined"
const id = 904
const url = '/items/' + id // "/items/904" — конкатенация через +
Шаблонные строки тоже приводят вложенные выражения к строке:
const eta = 12
`Доставка через ${eta} мин` // "Доставка через 12 мин"
В число #
Number('38.5') // 38.5
Number('') // 0
Number(' 9 ') // 9
Number('9px') // NaN
Number(true) // 1
Number(false) // 0
Number(null) // 0
Number(undefined) // NaN
Унарный плюс — краткий вариант Number(...):
const raw = '150'
const price = +raw // 150
parseInt / parseFloat читают число с начала строки и останавливаются на мусоре — удобно для '150₽', опасно для '150.5.1':
parseInt('150₽', 10) // 150
parseFloat('3.14em') // 3.14
Number('150₽') // NaN
Всегда передавайте основание 10 в parseInt, если парсите десятичные строки пользователя.
В boolean #
Boolean(0) // false
Boolean('') // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(NaN) // false
Boolean('0') // true — непустая строка
Boolean([]) // true — массив как объект
Boolean({}) // true
Двойное отрицание !!value — привычный способ получить true/false из любого значения.
Неявное приведение #
Операторы сами выбирают правила. Самые частые:
1 + '2' // "12" — если есть строка, + чаще конкатенирует
'6' * '7' // 42 — арифметика * / - приводит к числу
'10' - 1 // 9
true + 1 // 2
Сравнение через == запускает сложный алгоритм приведения — поэтому в JSFlow и в большинстве гайдлайнов рекомендуют ===:
'' == 0 // true
null == undefined // true
null === undefined // false
Таблица: что считается «пустым» в условиях #
| Значение | В if (value) |
|---|---|
0, -0, 0n | ложь |
'' | ложь |
null, undefined | ложь |
NaN | ложь |
false | ложь |
Остальное (включая '0', [], {}) | истина |
const input = '0'
if (input) {
// выполнится: строка не пустая
}
if (Number(input)) {
// не выполнится: число 0 — falsy
}
Перед проверкой решайте, что для домена означает «пусто»: ноль, пустая строка или отсутствие значения (null).
Практические рецепты #
function toFiniteNumber(value, fallback = 0) {
const n = Number(value)
return Number.isFinite(n) ? n : fallback
}
toFiniteNumber('42') // 42
toFiniteNumber('—') // 0
toFiniteNumber(undefined, -1) // -1
function asNonEmptyString(value) {
if (value == null) return ''
return String(value).trim()
}
asNonEmptyString(' JSFlow ') // "JSFlow"
Number.isFinite лучше, чем глобальный isFinite: не приводит аргумент через Number молча для любых типов одинаково удобно в строгих проверках.
Итог #
- Явно приводите через
String,Number,Boolean(или!!), когда важен контракт данных. +со строкой конкатенирует; остальные арифметические операторы тянут к числу.- Не полагайтесь на
==; используйте===и заранее нормализуйте вход. - Пустая строка,
0иnull— разные бизнес-смыслы, не смешивайте их в одной проверке бездумно.