Неявное приведение
Операторы -, * и / работают только с числами, а + умеет ещё и склеивать строки. Поэтому со строкой и числом + работает иначе, чем -, * и /:
console.log("4" + 2); // 42
console.log("4" - 2); // 2
console.log("4" * "2"); // 8
console.log(typeof ("4" + 2)); // stringДавайте разберём программу по строкам:
"4" + 2печатает42: двойка приклеилась к строке."4" - 2печатает2: минус превратил строку в число и вычел."4" * "2"печатает8: умножение превратило в числа обе строки.typeof ("4" + 2)печатаетstring: результат сложения — строка.
Ни Number, ни String в этой программе нет, но типы всё равно меняются. Смену типа, которую JavaScript делает сам, называют неявным приведением. Его же делает == из урока о сравнении, когда типы сторон разные: тот кассир тоже сам менял валюту перед сравнением.
Неявное приведение похоже на обменник, который меняет деньги без спроса. Вы ни о чём не просили, а значение уже другого типа. Поэтому такие места в коде часто не замечают, пока не появится неверный результат.
Плюс и строки
Если хотя бы одна сторона + — строка, вторая тоже превращается в строку, и строки склеиваются. Склеивание строк называют конкатенацией.
Выражение считается слева направо, поэтому важен порядок:
- в
1 + 2 + "3"сначала1 + 2даёт число3, и выходит"33"; "1" + 2 + 3с первого шага склеивает строки и даёт"123".
Составное присваивание += тоже склеивает, если в переменной строка. Так строку собирают по частям, начиная с пустой: "" + 1 — это строка "1".
let out = "";
out += 1;
out += 2;
console.log(out, typeof out); // 12 string
console.log(1 + 2 + "3", "1" + 2 + 3); // 33 123Разберём по шагам:
outначинается с пустой строки.out += 1даёт строку"1", аout += 2приклеивает к ней двойку:"12".- Программа печатает
12 string. - Последняя строка печатает
33 123: порядок шагов решает, когда начинается склеивание.
Этот вопрос постоянно задают на собеседовании: что получится, если сложить строку с числом, а что — если вычесть.
Остальная арифметика
Операторы -, *, /, % и ** всегда превращают обе стороны в число, как это делает Number. Минус перед одной строкой тоже даёт число: -"5" — это -5. Если строка не похожа на число, получается NaN. Дальше NaN распространяется: -, *, / и + с числом снова дают NaN.
Проверить результат помогает функция Number.isNaN(x): она возвращает true, только если x — это NaN. Сравнение через === здесь не поможет, ведь NaN не равен даже себе.
Выбор из двух значений
Выбрать одно из двух значений по результату проверки, например Number.isNaN, помогает тернарный оператор условие ? a : b. Его удобно читать как вопрос: «условие верно? тогда a, иначе b».
Как он работает:
- условием может быть любое значение: оно проверяется как истинное или ложное, по тем же правилам, что у
&&и||; - если условие истинное, оператор возвращает
a, иначеb; - это единственный оператор JavaScript, которому нужны три значения.
console.log("10" / "4", "a" * 2); // 2.5 NaN
const total = "a" * 2 + 1;
console.log(total, Number.isNaN(total)); // NaN true
const safe = Number.isNaN(total) ? 0 : total;
console.log(safe); // 0Разберём по строкам:
"10" / "4"даёт2.5, а"a" * 2даётNaN: строка"a"не похожа на число.totalполучаетNaN, потому чтоNaN + 1— сноваNaN.Number.isNaN(total)печатаетtrue.- Условие тернарного оператора истинное, поэтому он возвращает
0, и программа печатает0.
Частая ошибка
К числу из строки прибавляют единицу и ждут следующее число:
const input = "5";
const next = input + 1; // ✗
console.log(next); // 51Слева от + строка, поэтому единица приклеилась к ней, и вышло "51". Вычитание в той же программе сработало бы верно: input - 1 даёт 4, потому что - всегда превращает строку в число. Сначала превратите строку в число: Number(input) + 1 даёт 6.
Главное
- Если одна сторона
+— строка,+склеивает строки; выражение считается слева направо. -,*,/,%и**всегда превращают стороны в числа, а неудача даётNaN, который расходится дальше.Number.isNaN(x)проверяет, чтоx— этоNaN.условие ? a : bвозвращаетaпри истинном условии иbпри ложном.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.