Операторы и математика

данные≈ 7 минут

Здесь будет встроен видео-разбор темы (5–7 минут, YouTube / RuTube / VK Видео) — тем, кто лучше воспринимает на слух, текст ниже не обязателен.

Оператор — это действие над данными: сложить, сравнить, выбрать одно из двух. Большая часть знакома со школы, но у JavaScript есть и собственные фокусы — вроде плюса, который ничего не складывает, и строки "2", которая больше "12".

Разделы темы:·

Два слова из жаргона, которые пригодятся: операнд — то, к чему оператор применяется (в записи 5 * 2 операнды — пятёрка и двойка), а сам оператор бывает бинарным (два операнда) или унарным (один). Сложение, вычитание, умножение и деление работают ровно так, как вы ждёте:

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Дальше два оператора, которых в школьной тетради не было. Знак % — это не проценты, а остаток от деления: 10 % 3 означает «сколько останется, если из десяти забрать все целые тройки». Самое частое применение — проверка чётности: у чётного числа остаток от деления на 2 всегда ноль. А ** возводит в степень.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Оператор ** принимает и дробные степени, а из математики известно: степень 1/2 — квадратный корень, 1/3 — кубический. Так что корень можно взять без всяких специальных функций.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Оговорка: дробная степень считается приближённо, и везение примера выше не правило — 64 ** (1 / 3) вернёт 3.9999999999999996 вместо тройки. Поэтому в расчётах корень берут не степенью, а Math.sqrt и Math.cbrt: они сделаны ровно под это и не промахиваются.

У плюса есть вторая жизнь. Бинарный a + b складывает, а унарный — стоящий перед одним операндом — ничего не прибавляет, зато превращает операнд в число. С числом он не делает ничего, а вот строку или булево значение конвертирует — ровно как функция Number(), только на семь символов короче. Одно исключение: bigint унарный плюс не берёт вовсе — на +10n он бросает TypeError, а Number(10n) спокойно отдаёт 10.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Зачем это нужно? Данные из HTML-форм и сетевых запросов почти всегда приходят строками. Если сложить две такие «строки-числа» обычным плюсом, они склеятся, а не сложатся — плюс при виде строки работает как клей. Унарный плюс чинит это в одно движение:

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Когда в выражении несколько операторов, порядок определяет приоритет — у каждого оператора есть свой номер в длинной официальной таблице. Запоминать её не нужно, достаточно интуиции из школы: унарные операторы сильнее бинарных (поэтому в примере выше +apples сработал раньше сложения), умножение и деление сильнее сложения и вычитания. А всё, что хочется сделать первым, просто берётся в скобки — у них приоритет выше всех.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Практическое правило: если при чтении выражения приходится вспоминать таблицу приоритетов — поставьте скобки. Интерпретатору всё равно, а человеку, который будет читать код после вас, станет заметно легче.

Увеличение и уменьшение на единицу — настолько частая операция, что для неё выделили отдельные операторы: ++ (инкремент) и -- (декремент). Применять их можно только к переменным — запись 5++ вызовет ошибку, ведь пятёрку нельзя «изменить».

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Тонкость в том, что ++ можно поставить и до, и после переменной, и переменная в обоих случаях увеличится одинаково. Разница видна, только когда результат сразу используется: префиксная форма ++a возвращает уже новое значение, а постфиксная a++ — ещё старое.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

++i — сначала прибавь, потом отдай. i++ — сначала отдай.

Операторы сравнения — >, <, >=, <= — всегда возвращают булево значение: true или false. Результат можно сохранить в переменную или использовать сразу.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Сравнивать можно и строки — JavaScript идёт по ним посимвольно, как при расстановке слов в словаре: сравнил первые символы, при равенстве перешёл ко вторым, и так далее. Для слов это работает ожидаемо, а вот для «строк-чисел» превращается в ловушку: сравниваются символы, а не величины.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

В примере с "2" > "12" JavaScript сравнил первые символы — "2" и "1" — и на этом остановился: двойка в таблице символов дальше единицы, значит true. Если операнды означают числа, приведите их к числам унарным плюсом до сравнения — и ловушка исчезнет. Остальные странности сравнений — почему операнды разных типов становятся числами и почему null равен только undefined — разбирает статья «Сравнения и их ловушки».

Единственный оператор с тремя операндами — потому и тернарный. Записывается как условие ? значение1 : значение2 и читается как вопрос: условие истинно? Тогда возьми первое значение, иначе — второе. Это самый короткий способ выбрать одно из двух.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Тернарный оператор хорош именно для выбора значения. Когда по условию нужно выполнить разные действия или ветвление разрастается, читаемее конструкция if/else — её и сам тернарный оператор в роли ветвления разбирает статья «Условия: if, else и тернарный оператор».

В JavaScript есть и оператор , — он вычисляет несколько выражений подряд, а возвращает результат только последнего. Встречается в минифицированном коде и старых хитрых циклах, но в своём коде он не нужен: то же самое яснее записывается отдельными строками.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

  • Арифметика почти школьная, но с двумя новичками: % — остаток от деления (удобен для проверки чётности), ** — возведение в степень.
  • Унарный плюс +x — самый короткий способ превратить строку в число; Number(x) делает то же и вдобавок умеет bigint, которого плюс не берёт.
  • Не помните приоритет операторов — ставьте скобки: они главнее любой таблицы и делают код читаемее.
  • ++i возвращает уже увеличенное значение, i++ — ещё старое; сама переменная растёт в обоих случаях.
  • Строки сравниваются посимвольно, поэтому "2" > "12" — true; а выбор одного из двух значений удобно записывать тернарным оператором условие ? а : б.

1/3Что выведет console.log(2 + 2 * 2)?

2/3Есть код: let i = 5; console.log(i++); Что попадёт в консоль?

3/3Что вернёт выражение "2" > "12"?

Та же сумма, но короче

Тот же случай, что в задаче «Почини сумму» из статьи «Преобразование типов: где JavaScript вас удивит»: данные пришли из формы, поэтому оба значения — строки, и код печатает "105". Только теперь под рукой унарный плюс. Исправьте последнюю строку так, чтобы вывелось число 15, не трогая объявления переменных.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Унарный плюс превращает каждую строку в число ещё до сложения: console.log(+a + +b); // 15. Унарные операторы срабатывают раньше бинарного плюса, поэтому дополнительные скобки не нужны.

Предскажи инкременты

Не запуская код, определите, что напечатает каждый console.log. Потом запустите и сверьтесь.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

++a увеличивает a до 2 и возвращает 2 — это b. Затем a++ возвращает текущие 2 (это c) и после увеличивает a до 3. Вывод: 3, 2, 2.