Оператор — это символ или группа символов, которые представляют какую-то операцию: арифметическую, логическую, присваивания и так далее. В математике самые известные операторы — это знаки плюса, минуса, умножения и деления. В JavaScript тоже есть свои операторы, и точно так же, как и в математике, в программировании есть определённый порядок, в котором все эти операторы выполняются. Если не знать приоритета операций, можно написать неправильный код, который будет делать не то, что задумал программист. Чтобы этого не было, расскажем про основные операторы в JS и их приоритеты.
Операторы и операнды
Сразу разберёмся с базовыми понятиями: оператор и операнд. Чтобы было проще, покажем это на простом примере:
2 + 3
Здесь знак сложения (плюс) — это оператор, а числа, которые мы складываем (2 и 3), — это операнды. Ещё можно запомнить так: оператор — это то, что мы делаем, а операнд — с чем мы это делаем.
В JS есть разные типы операторов, мы поговорим про те, которые используются чаще всего.
Математические операторы:
- Инкремент:
++
- Декремент:
--
- Возведение в степень:
**
- Взятие остатка от деления:
%
- Умножение:
*
- Деление:
/
- Сложение:
+
- Вычитание:
-
Логические операторы:
- ! (НЕ)
- && (И)
- || (ИЛИ)
Отдельно рассмотрим оператор последовательного присваивания:
- a = b = c
Если взять выражение console.log(8 + 2)
, то + в нём будет оператором сложения, а числа 8
и 2
— операндами. Действие, которое оператор производит над операндами, — это операция.
В зависимости от количества операндов операции бывают:
- унарные — когда используется только один операнд;
- бинарные — когда операндов два;
- и тернарные — когда их три.
В нашем примере (8 + 2)
— это бинарная операция, поскольку оператор +
действует на два операнда: 8
и 2
.
Хорошим тоном при написании кода считается отбивать операторы от операндов пробелами: когда операторов много, такой код легче воспринимать.
Общий приоритет операторов
Приоритет определяет то, в какой последовательности должны выполняться операции. В JS всё так же, как и в обычной математике, и операторы выполняются в следующем порядке:
- Операторы инкремента
++
и декремента--
- Возведение в степень
**
- Умножение
*
, деление/
, взятие остатка от деления%
- Сложение
+
, вычитание-
- Логические операторы НЕ (!), И (&&), ИЛИ (||)
- Последовательное присваивание
= =
Если подряд идут операции с одинаковым приоритетом, они выполняются слева направо. Операция последовательного присваивания выполняется справа налево.
Инкремент и декремент
Инкремент ++
и декремент --
используют для увеличения или уменьшения значения своего операнда на единицу. При этом есть разница, стоят ли эти два знака до или после переменной. Если до, то сначала значение переменной увеличится (или уменьшится) на единицу, а потом будет выполняться всё остальное. А если они стоят после переменной, то сначала посчитается всё выражение и только потом значение переменной увеличится на единицу.
Ставим инкремент в начало и смотрим на результат. По правилам мы сначала увеличим значение переменной, а потом будет происходить всё остальное:
let x = 0;
console.log(++x + 2);
Логика такая:
- Мы задали переменную x.
- Сразу увеличили значение переменной на единицу, потому что инкремент стоит до переменной. Теперь в переменной X будет значение 1.
- Прибавили к ней два обычным сложением — 1 + 2 = 3. Этот результат и появился на экране.
Теперь проверим, как работает инкремент после переменной:
let x = 0;
console.log(x++ + 2);
Вот что произошло:
- Мы задали переменную
x
. - Прибавили к ней два обычным сложением — 0 + 2 = 2. Этот результат и появился на экране.
- И только потом увеличили значение переменной на единицу. Теперь в переменной X будет значение 1.
Возведение в степень
Следующий оператор — возведение в степень **
. Он выше всех остальных арифметических операций:
console.log(2 ** 3 * 2)
В примере сначала возводим 2 в степень 3, а затем умножаем на 2:
- 2³ = 8
- 8 × 2 = 16
Умножение, деление и взятие остатка
Обозначаются они так: умножение *
, деление /
и взятие остатка от деления %
. Эти операции выполняются до сложения или вычитания:
console.log(48 / 6 * 2);
Здесь идут две операции, имеющие одинаковый приоритет. Поэтому сначала 48 делим на 6 и получаем 8, а потом умножаем результат на 2, что даёт 16.
Оператор взятия остатка от деления имеет тот же приоритет, что умножение и деление.
console.log(10 % 4 * 2);
Решаем пример слева направо: сначала 10 делим на 4 с остатком, затем 2 умножаем на 2, что даёт 4.
Сложение и вычитание
Сложение +
и вычитание -
имеют наименьший приоритет.
console.log(20 - 2 + 2 * 2 ** 2);
- Выполняем возведение в степень
2 ** 2 = 4
. - Затем умножаем
2 * 4 = 8
. - После этого слева направо выполняем операции вычитания и сложения. Сначала
20 - 2 = 18
, затем18 + 8 = 26
:
Приоритеты логических операторов
Логические операторы используются для проверки и определения истинности между двумя или более операндами.
!
— «НЕ» (отрицание). Если операнд истинен, то оператор НЕ превращает его в ложный, и наоборот. Имеет самый высокий приоритет.&&
— «И» (в матлогике это называют конъюнкцией). Всё выражение считается истинным только в том случае, когда истинен каждый операнд. Выполняется только после всех операций НЕ.||
— «ИЛИ» (дизъюнкция). Выражение считается истинным, если истинен хотя бы один операнд. Имеет самый низкий приоритет среди логических операторов.
Разберём приоритетность на вот таком примере:
console.log(true || false && !false);
- Сначала выполнится оператор НЕ, превращая
false
вtrue
. - Затем выполнится оператор И:
false && true
даётfalse
. - Наконец, выполняется оператор ИЛИ:
true || false
даётtrue
.
Логические операторы имеют более низкий приоритет, чем арифметические, поэтому выполняются после арифметических действий
let a = 5, b = 10, c = 15;
console.log(a + b * c > 50 || b - c > 0);
- Задаём три переменные.
- Сначала делаем умножение
b * c
, получаем150
. - Затем складываем
a + 150 = 155
. - После этого сравниваем
155 > 50
, получаемtrue
. - Во второй части выражения получаем
-5
. - Сравниваем его с нулём и получаем
false
. - И в самом конце производим операцию ИЛИ:
(true || false)
, которая возвращаетtrue
.
В этом примере мы также использовали операторы сравнения. Они имеют средний приоритет: выше, чем у логических операторов, но ниже, чем у арифметических.
Приоритет оператора присваивания подряд
Оператор присваивания подряд используется для установки значения переменной или свойства объекта. Его можно использовать последовательно, что позволяет одновременно присвоить одно и то же значение нескольким переменным. Выполняется справа налево.
Оператор присваивания (=
) имеет один из самых низких приоритетов среди всех операторов и выполняется последним:
let a, b, c;
a = b = c = 10;
console.log(a, b, c);
- Задаём три переменные.
- Последовательно присваиваем им значение.
- Сначала переменной
c
присваивается значение10
. - Затем результат этого присваивания используется для выражения
b = c
, что означает присваиваниеb
значения 10. - Наконец,
a = b
присваивает переменнойa
значение10
.
Теперь объединим все операторы и посмотрим, как они выполняются:
let a, b, c, d;
a = b = c = 10 + 5;
d = (b = b + 5) || (c = c + 10);
console.log(a, b, c, d);
Во второй строке сначала выполняется сложение, а затем последовательное присвоение.
В выражении b = b + 5
выполняется первым b + 5
присваивается значение , а затем
b
20
. Поскольку левая сторона оператора ИЛИ уже истинна (20), то правая сторона (c = c + 10
) не выполняется. Наконец, d
присваивается значение левой части выражения после присваивания: 20
.
Таким образом, мы получаем:
Как переопределить приоритет
Иногда вычисления нужно делать в порядке, отличном от стандартного приоритета. Тогда приоритет задаётся круглыми скобками, точно так же, как в школе:
(2 + 2) * 2
То, что в скобках, вычисляется в первую очередь. Затем слева направо вычисляется всё остальное: сначала умножение и деление, потом сложение и вычитание.
Скобки можно ставить вокруг любой операции. Они могут вкладываться друг в друга сколько угодно раз:
console.log(7 * 3 + (4 / 2) - (8 + (2 - 1)));
- Сначала выполняются операции в скобках на самом низком уровне вложенности (4 / 2) и (2 - 1).
- Затем вычисляется получившееся выражение 7 * 3 + 2 - (8 + 1).
- Снова выполняются скобки, а затем операторы в порядке приоритета: умножение, сложение и вычитание.
А ещё можно расставить скобки, чтобы выражение было проще воспринимать визуально, но при этом приоритет не менялся.
Было так:
console.log(8 / 2 + 5 - -3 / 2);
А стало так:
console.log(((8 / 2) + 5) - (-3 / 2));
Логические операторы также можно комбинировать в любом количестве и любой последовательности:
let a = true, b = false, c = true;
console.log((a || b) && c);
Поскольку оператор ИЛИ в скобках, то (a || b)
выполняется первым, а уже потом выполняется оператор И.
В сложных логических выражениях, где используются одновременно &&
и ||
, лучше использовать скобки для явного указания порядка операций, чтобы избежать путаницы в логике программы.