Menu

Операторы в JavaScript: полный разбор с примерами

Разбираем операторы JavaScript - арифметические, сравнения, логические, присваивания и не только. С теми подводными камнями, на которые реально натыкаешься в коде.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Операторы - это то, как выражения выполняют работу

Практически любая нетривиальная строка JavaScript состоит из операторов - символов, которые берут одно или два значения и возвращают новое. + складывает, === сравнивает, && объединяет булевы значения, ? : выбирает одно из двух. Большинство операторов в js знакомы по другим языкам, но у некоторых есть свои особенности, о которых стоит знать заранее.

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

Арифметические операторы

С базовыми всё предсказуемо:

Стоит обратить внимание на несколько моментов:

  • / - это всегда деление с плавающей точкой. 7 / 2 даст 3.5, а не 3. Если нужен именно целочисленный результат, используйте Math.floor(7 / 2) или Math.trunc(7 / 2).
  • % возвращает остаток, а не математический модуль. Знак результата совпадает со знаком левого операнда: -7 % 3 - это -1, а не 2.
  • + - оператор с двойным смыслом. Если хотя бы один из операндов - строка, происходит не сложение, а конкатенация: "3" + 1 даёт "31". Об этом чуть ниже подробнее.

Инкремент и декремент

Разница между count++ и ++count проявляется только тогда, когда значение выражения используется прямо в той же строке. Если это самостоятельный оператор, они делают одно и то же. Большинство стайл-гайдов вообще рекомендуют писать count += 1 - так понятнее.

У оператора + раздвоение личности

Вот на этом хоть раз спотыкался каждый:

Если хотя бы один из операндов - строка, + превращается в конкатенацию и приводит вторую сторону к строке. Все остальные арифметические операторы работают наоборот: строки приводятся к числам:

Главное правило: когда собираете строки - используйте шаблонные литералы (`price: ${5}`). А когда считаете числа - убедитесь, что на вход действительно приходят числа: Number(x) или parseInt(x, 10) приводят типы явно.

Операторы сравнения в JavaScript

Операторы сравнения возвращают булево значение. Есть два варианта: строгое и нестрогое сравнение.

=== и !== - это строгое сравнение: и значение, и тип должны совпадать. А вот == и != сначала приводят типы, и из-за этого случаются сюрпризы вроде null == undefined, который возвращает true, или [] == false, тоже true. По умолчанию используйте === и !==. Единственное распространённое исключение - конструкция x == null: удобный способ проверить, равно ли x либо null, либо undefined.

Операторы сравнения работают с числами так, как и ожидаешь, а со строками - по алфавиту:

Сравнение строк идёт по кодам символов, поэтому регистр имеет значение. Если нужна «человеческая» сортировка - используйте String.prototype.localeCompare.

Логические операторы js

&& (И), || (ИЛИ) и ! (НЕ) умеют комбинировать булевы значения - но на практике они работают интереснее, чем можно было бы ожидать от чистой булевой алгебры.

Нюанс вот в чём: && и || возвращают не true или false, а один из своих операндов. && вернёт первое falsy-значение, либо последнее, если все значения truthy. || - первое truthy-значение, либо последнее, если все falsy.

Именно поэтому вы часто встретите такие конструкции, как const displayName = user.name || "Guest" - берём первое непустое значение. Коротко и ёмко, но есть нюанс: || считает 0, "" и false поводом взять запасной вариант. Если для вас это валидные значения, используйте ?? (о нём ниже).

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

Оператор нулевого слияния ??

Оператор ?? в javascript работает похоже на ||, но срабатывает только на null или undefined - значения 0, "" и false он пропускает как вполне валидные.

Используйте ??, если валидным значением может быть что-то ложное - ноль, пустая строка, явный false. А || берите, когда любое ложное значение должно означать «ничего нет». В современном коде ?? - более безопасный выбор по умолчанию для необязательных значений с ненулевым дефолтом.

Оператор присваивания в JavaScript

= просто присваивает значение. Составные формы объединяют присваивание с каким-нибудь другим оператором:

Есть ещё логические операторы присваивания - ||=, &&= и ??=, которые записывают новое значение только при выполнении определённого условия:

Такие конструкции удобны, когда нужно подставить значение по умолчанию без громоздких if.

Тернарный оператор в JavaScript

Запись условие ? a : b - это выражение-аналог if/else. Если условие истинно, возвращается a, иначе - b:

Тернарный оператор хорош для коротких выборок значения. Но как только вы начинаете его вкладывать - превращается в головоломку: если у вас получается a ? b : c ? d : e, лучше взять if/else или объект-словарь.

Оператор typeof и instanceof в JavaScript

Оператор typeof возвращает строку с типом своего операнда:

Пара граблей, которые стоит запомнить раз и навсегда: typeof null возвращает "object" (баг из 1995 года, который уже никогда не починят), а массивы тоже определяются как "object". Поэтому для массивов используйте Array.isArray(x), а для null - обычное x === null.

Оператор instanceof проверяет, был ли объект создан на основе конкретного конструктора:

Spread и rest - один и тот же ...

Синтаксис ... встречается в двух ситуациях. В роли spread он «разворачивает» итерируемый объект на отдельные элементы:

В роли rest он, наоборот, собирает несколько значений в один массив - обычно в параметрах функции или при деструктуризации:

Синтаксис один - задачи противоположные. Spread распаковывает, rest собирает. Кто из них кто - решает контекст: в вызове или литерале это spread, в списке параметров или шаблоне деструктуризации - rest.

Приоритет операторов в JavaScript (если сомневаетесь - ставьте скобки)

У операторов есть приоритет, который определяет, какой из них выполнится первым, когда вы их смешиваете. Умножение важнее сложения, сравнение важнее логических операторов, и так далее:

Полную таблицу никто наизусть не держит - да это и не нужно. Простая привычка закрывает 99% случаев: если в выражении смешаны разные операторы и вы не уверены в порядке вычислений - ставьте скобки. Код становится читаемее и не зависит от памяти того, кто его читает.

Побитовые операторы (скорее всего, вам не они нужны)

Для полноты картины: &, |, ^, ~, <<, >> и >>> работают с двоичным представлением целых чисел. Встретить их можно в коде для графики, в низкоуровневых протоколах и изредка - в API с флагами-битмасками.

Один распространённый, но сомнительный трюк: n | 0 усекает число до 32-битного целого, и раньше это использовали как более быструю замену Math.trunc. Не надо так - Math.trunc понятнее и работает с числами за пределами 32-битного диапазона.

Дальше: if/else

Операторы возвращают значения, а if/else на основе этих значений выбирает, какую ветку кода выполнить. По сути, большую часть времени вы будете скармливать результаты операторов сравнения и логических операторов именно в условные конструкции - об этом и пойдёт речь на следующей странице.

Часто задаваемые вопросы

Какие основные операторы есть в JavaScript?

В JavaScript есть арифметические (+, -, *, /, %, **), сравнения (===, !==, <, >), логические (&&, ||, !), присваивания (=, +=, -=), а также несколько специальных: тернарный ? :, typeof и оператор нулевого слияния ??. Из них и собираются все выражения и условия в коде.

Чем отличается == от === в JavaScript?

=== сравнивает и значение, и тип - строго. А == сначала приводит типы, поэтому 0 == "0" даёт true, хотя 0 === "0" - это false. По умолчанию всегда используйте ===: правила приведения у == достаточно хитрые, чтобы породить баг, который никто не заметит на ревью.

Что делает тернарный оператор в JavaScript?

condition ? a : b - это однострочный if/else, который возвращает значение. Если condition истинно, выражение равно a, иначе - b. Удобно для коротких условий вроде const label = count === 1 ? 'item' : 'items', но вложенные тернарники быстро превращаются в нечитаемую кашу.

Когда использовать ?? вместо ||?

|| срабатывает на любое falsy-значение - включая 0, "" и false. А ?? реагирует только на null и undefined. Если в count ?? 10 вам важно сохранить честный 0 - берите ??. Если же вы действительно хотите, чтобы любое falsy-значение включало fallback, оставляйте ||.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ