Для работы с переменными, со значениями, JavaScript поддерживает все стандартные операторы, большинство которых есть и в других языках программирования.
Несколько операторов мы знаем со школы – это обычные сложение +
, умножение *
, вычитание и так далее.
В этой главе мы сконцентрируемся на операторах, которые в курсе математики не проходят, и на их особенностях в JavaScript.
У операторов есть своя терминология, которая используется во всех языках программирования.
Прежде, чем мы двинемся дальше – несколько терминов, чтобы понимать, о чём речь.
Операнд – то, к чему применяется оператор. Например: 5 * 2
– оператор умножения с левым и правым операндами. Другое название: «аргумент оператора».
Унарным называется оператор, который применяется к одному операнду. Например, оператор унарный минус "-"
меняет знак числа на противоположный:
Бинарным называется оператор, который применяется к двум операндам. Тот же минус существует и в бинарной форме:
Обычно при помощи плюса '+'
складывают числа.
Но если бинарный оператор '+'
применить к строкам, то он их объединяет в одну:
Иначе говорят, что «плюс производит конкатенацию (сложение) строк».
Если хотя бы один аргумент является строкой, то второй будет также преобразован к строке!
Причем не важно, справа или слева находится операнд-строка, в любом случае нестроковый аргумент будет преобразован. Например:
Это приведение к строке – особенность исключительно бинарного оператора "+"
.
Остальные арифметические операторы работают только с числами и всегда приводят аргументы к числу.
Например:
Унарный, то есть применённый к одному значению, плюс ничего не делает с числами:
Как видно, плюс ничего не изменил в выражениях. Результат – такой же, как и без него.
Тем не менее, он широко применяется, так как его «побочный эффект» – преобразование значения в число.
Например, когда мы получаем значения из HTML-полей или от пользователя, то они обычно в форме строк.
А что, если их нужно, к примеру, сложить? Бинарный плюс сложит их как строки:
Поэтому используем унарный плюс, чтобы преобразовать к числу:
С точки зрения математики такое изобилие плюсов может показаться странным. С точки зрения программирования – никаких разночтений: сначала выполнятся унарные плюсы, приведут строки к числам, а затем – бинарный '+'
их сложит.
Почему унарные плюсы выполнились до бинарного сложения? Как мы сейчас увидим, дело в их приоритете.
В том случае, если в выражении есть несколько операторов – порядок их выполнения определяется приоритетом.
Из школы мы знаем, что умножение в выражении 2 * 2 + 1
выполнится раньше сложения, т.к. его приоритет выше, а скобки явно задают порядок выполнения. Но в JavaScript – гораздо больше операторов, поэтому существует целая таблица приоритетов.
Она содержит как уже пройденные операторы, так и те, которые мы еще не проходили. В ней каждому оператору задан числовой приоритет. Тот, у кого число больше – выполнится раньше. Если приоритет одинаковый, то порядок выполнения – слева направо.
Отрывок из таблицы:
Приоритет | Название | Обозначение |
---|---|---|
… | … | … |
15 | унарный плюс | + |
15 | унарный минус | - |
14 | умножение | * |
14 | деление | / |
13 | сложение | + |
13 | вычитание | - |
… | … | … |
3 | присваивание | = |
… | … | … |
Так как «унарный плюс» имеет приоритет 15
, выше, чем 13
у обычного «сложения», то в выражении +apples + +oranges
сначала сработали плюсы у apples
и oranges
, а затем уже обычное сложение.
Обратим внимание, в таблице приоритетов также есть оператор присваивания =
.
У него – один из самых низких приоритетов: 3
.
Именно поэтому, когда переменную чему-либо присваивают, например, x = 2 * 2 + 1
сначала выполнится арифметика, а уже затем – произойдёт присваивание =
.
Возможно присваивание по цепочке:
Такое присваивание работает справа-налево, то есть сначала вычислятся самое правое выражение 2+2
, присвоится в c
, затем выполнится b = c
и, наконец, a = b
.
"="
возвращает значениеВсе операторы возвращают значение. Вызов x = выражение
не является исключением.
Он записывает выражение в x
, а затем возвращает его. Благодаря этому присваивание можно использовать как часть более сложного выражения:
В примере выше результатом (a = b + 1)
является значение, которое записывается в a
(т.е. 3
). Оно используется для вычисления c
.
Забавное применение присваивания, не так ли?
Знать, как это работает – стоит обязательно, а вот писать самому – только если вы уверены, что это сделает код более читаемым и понятным.
Оператор взятия остатка %
интересен тем, что, несмотря на обозначение, никакого отношения к процентам не имеет.
Его результат a % b
– это остаток от деления a
на b
.
Например:
++
, --
Одной из наиболее частых операций в JavaScript, как и во многих других языках программирования, является увеличение или уменьшение переменной на единицу.
Для этого существуют даже специальные операторы:
Инкремент ++
увеличивает на 1:
Декремент --
уменьшает на 1:
Инкремент/декремент можно применить только к переменной.
Код 5++
даст ошибку.
Вызывать эти операторы можно не только после, но и перед переменной: i++
(называется «постфиксная форма») или ++i
(«префиксная форма»).
Обе эти формы записи делают одно и то же: увеличивают на 1
.
Тем не менее, между ними существует разница. Она видна только в том случае, когда мы хотим не только увеличить/уменьшить переменную, но и использовать результат в том же выражении.
Например:
В строке (*)
вызов ++i
увеличит переменную, а затем вернёт ее значение в a
. Так что в a
попадёт значение i
после увеличения.
Постфиксная форма i++
отличается от префиксной ++i
тем, что возвращает старое значение, бывшее до увеличения.
В примере ниже в a
попадёт старое значение i
, равное 1
:
Если результат оператора не используется, а нужно только увеличить/уменьшить переменную – без разницы, какую форму использовать:
Если хочется тут же использовать результат, то нужна префиксная форма:
Если нужно увеличить, но нужно значение переменной до увеличения – постфиксная форма:
При этом он имеет более высокий приоритет и выполняется раньше, чем арифметические операции:
При этом, нужно с осторожностью использовать такую запись, потому что в более длинной строке при быстром «вертикальном» чтении кода легко пропустить такой i++
, и будет неочевидно, что переменая увеличивается.
Три строки, по одному действию в каждой – длиннее, зато нагляднее:
Побитовые операторы рассматривают аргументы как 32-разрядные целые числа и работают на уровне их внутреннего двоичного представления.
Эти операторы не являются чем-то специфичным для JavaScript, они поддерживаются в большинстве языков программирования.
Поддерживаются следующие побитовые операторы:
&
)|
)^
)~
)<<
)>>
)>>>
)Часто нужно применить оператор к переменной и сохранить результат в ней же, например:
Эту запись можно укоротить при помощи совмещённых операторов, вот так:
Так можно сделать для операторов +,-,*,/,%
и бинарных <<,>>,>>>,&,|,^
.
Вызов с присваиванием имеет в точности такой же приоритет, как обычное присваивание, то есть выполнится после большинства других операций:
Один из самых необычных операторов – запятая ','
.
Его можно вызвать явным образом, например:
Запятая позволяет перечислять выражения, разделяя их запятой ','
. Каждое из них – вычисляется и отбрасывается, за исключением последнего, которое возвращается.
Запятая – единственный оператор, приоритет которого ниже присваивания. В выражении a = (5,6)
для явного задания приоритета использованы скобки, иначе оператор '='
выполнился бы до запятой ','
, получилось бы (a=5), 6
.
Зачем же нужен такой странный оператор, который отбрасывает значения всех перечисленных выражений, кроме последнего?
Обычно он используется в составе более сложных конструкций, чтобы сделать несколько действий в одной строке. Например:
Такие трюки используются во многих JavaScript-фреймворках для укорачивания кода.