Перейти к содержимому
Теория · Операторы и приведение типов · урок 10 из 14

Неявное приведение

Операторы -, * и / работают только с числами, а + умеет ещё и склеивать строки. Поэтому со строкой и числом + работает иначе, чем -, * и /:

JavaScript
console.log("4" + 2); // 42
console.log("4" - 2); // 2
console.log("4" * "2"); // 8
console.log(typeof ("4" + 2)); // string

Давайте разберём программу по строкам:

  1. "4" + 2 печатает 42: двойка приклеилась к строке.
  2. "4" - 2 печатает 2: минус превратил строку в число и вычел.
  3. "4" * "2" печатает 8: умножение превратило в числа обе строки.
  4. typeof ("4" + 2) печатает string: результат сложения — строка.

Ни Number, ни String в этой программе нет, но типы всё равно меняются. Смену типа, которую JavaScript делает сам, называют неявным приведением. Его же делает == из урока о сравнении, когда типы сторон разные: тот кассир тоже сам менял валюту перед сравнением.

Неявное приведение похоже на обменник, который меняет деньги без спроса. Вы ни о чём не просили, а значение уже другого типа. Поэтому такие места в коде часто не замечают, пока не появится неверный результат.

Плюс и строки

Если хотя бы одна сторона + — строка, вторая тоже превращается в строку, и строки склеиваются. Склеивание строк называют конкатенацией.

Выражение считается слева направо, поэтому важен порядок:

  • в 1 + 2 + "3" сначала 1 + 2 даёт число 3, и выходит "33";
  • "1" + 2 + 3 с первого шага склеивает строки и даёт "123".

Составное присваивание += тоже склеивает, если в переменной строка. Так строку собирают по частям, начиная с пустой: "" + 1 — это строка "1".

JavaScript
let out = "";
out += 1;
out += 2;
console.log(out, typeof out); // 12 string
console.log(1 + 2 + "3", "1" + 2 + 3); // 33 123

Разберём по шагам:

  1. out начинается с пустой строки.
  2. out += 1 даёт строку "1", а out += 2 приклеивает к ней двойку: "12".
  3. Программа печатает 12 string.
  4. Последняя строка печатает 33 123: порядок шагов решает, когда начинается склеивание.

Этот вопрос постоянно задают на собеседовании: что получится, если сложить строку с числом, а что — если вычесть.

Остальная арифметика

Операторы -, *, /, % и ** всегда превращают обе стороны в число, как это делает Number. Минус перед одной строкой тоже даёт число: -"5" — это -5. Если строка не похожа на число, получается NaN. Дальше NaN распространяется: -, *, / и + с числом снова дают NaN.

Проверить результат помогает функция Number.isNaN(x): она возвращает true, только если x — это NaN. Сравнение через === здесь не поможет, ведь NaN не равен даже себе.

Выбор из двух значений

Выбрать одно из двух значений по результату проверки, например Number.isNaN, помогает тернарный оператор условие ? a : b. Его удобно читать как вопрос: «условие верно? тогда a, иначе b».

Как он работает:

  • условием может быть любое значение: оно проверяется как истинное или ложное, по тем же правилам, что у && и ||;
  • если условие истинное, оператор возвращает a, иначе b;
  • это единственный оператор JavaScript, которому нужны три значения.
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

Разберём по строкам:

  1. "10" / "4" даёт 2.5, а "a" * 2 даёт NaN: строка "a" не похожа на число.
  2. total получает NaN, потому что NaN + 1 — снова NaN.
  3. Number.isNaN(total) печатает true.
  4. Условие тернарного оператора истинное, поэтому он возвращает 0, и программа печатает 0.

Частая ошибка

К числу из строки прибавляют единицу и ждут следующее число:

JavaScript
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 и подпишись на канал — откроются все уроки.

Войти другим способом