Преобразование типов: где JavaScript вас удивит
Здесь будет встроен видео-разбор темы (5–7 минут, YouTube / RuTube / VK Видео) — тем, кто лучше воспринимает на слух, текст ниже не обязателен.
JavaScript охотно переводит значения из одного типа в другой: что-то вы просите сами, а что-то он делает молча — и именно тихие преобразования порождают самые загадочные баги. Разберём три явных преобразования и главную ловушку — оператор +.
Чаще всего преобразование в строку происходит без вашего участия: alert показывает именно строку, склейка со строкой тоже создаёт строку. Когда нужно явно — есть функция String().
Со строками всё честно: значение просто записывается буквами, без сюрпризов. Даже null и NaN становятся обычными словами.
Числовое преобразование запускается функцией Number(), а неявно — почти любой математикой: делением, умножением, сравнением. Правила здесь строже, чем у строк, и их стоит выучить наизусть.
| Значение | Number(значение) |
|---|---|
"" (пустая строка) | 0 |
" 12 " | 12 — пробелы по краям обрезаются |
"12px" | NaN |
null | 0 |
undefined | NaN |
true / false | 1 / 0 |
Авторы языка рассудили так: null — осознанная пустота, «здесь ничего нет», а пустоту посчитать можно — получается ноль. undefined означает «значение вообще не задавали», и превращать его в конкретное число было бы враньём — отсюда NaN, «не число».
Логическое преобразование — самое простое: весь мир делится на два лагеря. Ложных значений восемь: false, 0, -0, 0n, пустая строка "", null, undefined и NaN. Абсолютно всё остальное — true, и это правило молча срабатывает в каждом if. На практике чаще всего встречаются пять из восьми: 0, пустая строка, null, undefined и NaN; false, -0 и 0n попадаются реже. Полный список с разбором ждёт в статье «Условия: if, else и тернарный оператор».
Лжецов восемь: false, 0, -0, 0n, "", null, undefined, NaN. Всё остальное не врёт.
Подвох прячется в кавычках: "0" — не ноль, а строка из одного символа, поэтому она истинна. То же со строкой из пробела. Язык проверяет не «похоже ли на ноль», а «пустая ли строка».
У оператора + двойная жизнь: если хотя бы один операнд — строка, он бросает математику и склеивает строки. Остальные арифметические операторы — -, *, / — таких сомнений не знают и всегда переводят операнды в числа.
| Выражение | Результат | Почему |
|---|---|---|
"5" + 3 | "53" | число подтянулось к строке |
"5" - 3 | 2 | минус умеет только считать |
2 + 2 + "1" | "41" | слева направо: сначала 4, потом склейка |
"" - 1 | -1 | пустая строка стала нулём |
Правило простое: увидели + рядом со строкой — ждите строку. Данные из полей ввода и URL всегда приходят строками, поэтому перед сложением их нужно явно пропустить через Number() — с этой ловушкой мы уже сталкивались в статье «Диалоги браузера: alert, prompt, confirm», где строку отдавал prompt. Теперь видно, почему так: склеивает не prompt, а сам плюс. Как TypeScript ещё до запуска замечает число, незаметно ставшее строкой, покажет статья «Что компилятор находит в вашем коде из части I» в части III.
- Явных преобразований три:
String(x),Number(x),Boolean(x). - Правила
Number():""иnullдают0,undefinedи строки с мусором —NaN, пробелы по краям обрезаются. - Falsy-значений восемь:
false,0,-0,0n,"",null,undefined,NaN. Всё остальное —true, включая"0"и" ". +рядом со строкой склеивает;-,*и/всегда переводят операнды в числа.- Данные из форм и URL приходят строками — пропускайте их через
Number()до математики.
1/3Что выведет console.log(Number(" 7 "))?
2/3Какое из этих значений превратится в true после Boolean()?
3/3Что выведет console.log("2" + 1 + 1)?
Предскажи вывод
Не запуская код, запишите, что выведет каждая строка. Потом запустите и сверьтесь: расхождения точно покажут, какое правило ещё не улеглось.
Первая строка даёт "10" — плюс со строкой клеит. Дальше работают числа: -1 (пустая строка — это 0), -14 (пробелы обрезались, осталось -9), 1 (null превращается в 0) и NaN (undefined числом не становится).
Почини сумму
Значения пришли из полей формы, поэтому они строки. Исправьте код так, чтобы вместо "10020" вывелось 120.
Перед сложением превратите строки в числа: console.log(Number(price) + Number(delivery)). Теперь плюс не видит ни одной строки и честно считает.