# Основные операторы Для работы с переменными, со значениями, JavaScript поддерживает все стандартные операторы, большинство которых есть и в других языках программирования. [cut] ## Термины: "унарный", "бинарный", "операнд" У операторов есть своя терминология, которая используется во всех языках программирования. Некоторые операторы, например, вычитание `"-"` и сложение `"+"`, бывают в двух вариантах: унарный -- при применении к одному операнду, и бинарный -- к двум. ## Арифметические операторы **Базовые арифметические операторы знакомы нам с детства: это плюс `+`, минус `-`, умножить `*`, поделить `/`.** Например: ```js //+ run alert(2 + 2); // 4 ``` Или чуть сложнее: ```js //+ run var i = 2; i = (2 + i) * 3 / i; alert(i); // 6 ``` **Более редкий арифметический оператор `%` интересен тем, что никакого отношения к процентам не имеет. Его результат `a % b` -- это остаток от деления `a` на `b`.** Например: ```js //+ run alert(5 % 2); // 1, остаток от деления 5 на 2 alert(8 % 3); // 2, остаток от деления 8 на 3 alert(6 % 3); // 0, остаток от деления 6 на 3 ``` ### Сложение строк, бинарный + Если бинарный оператор `+` применить к строкам, то он их объединяет в одну: ```js var a = "моя" + "строка"; alert(a); // моястрока ``` **Если хотя бы один аргумент является строкой, то второй будет также преобразован к строке!** Причем не важно, справа или слева находится операнд-строка, в любом случае нестроковый аргумент будет преобразован. Например: ```js //+ run alert( '1' + 2 ); // "12" alert( 2 + '1' ); // "21" ``` Это приведение к строке -- особенность бинарного оператора `"+"`. **Остальные арифметические операторы работают только с числами и всегда приводят аргументы к числу.** Например: ```js //+ run alert( '1' - 2 ); // -1 alert( 6 / '2'); // 3 ``` ### Унарный плюс + Унарный, то есть применённый к одному значению, плюс как арифметический оператор ничего не делает: ```js //+ run alert( +1 ); // 1 alert( +(1-2) ); // -1 ``` Как видно, плюс ничего не изменил в выражениях. Результат -- такой же, как и без него. Тем не менее, он широко применяется, так как его "побочный эффект" -- преобразование значения в число. Например, у нас есть два числа, в форме строк, и нужно их сложить. Бинарный плюс сложит их как строки, поэтому используем унарный плюс, чтобы преобразовать к числу: ```js //+ run var a = "2"; var b = "3"; alert( a + b ); // "23", так как бинарный плюс складывает строки alert( +a + b ); // "23", второй операнд - всё ещё строка alert( +a + +b); // 5, число, так как оба операнда предварительно преобразованы в числа ``` ## Присваивание Оператор присваивания выглядит как знак равенства `=`: ```js var i = 1 + 2; alert(i); // 3 ``` Он вычисляет выражение, которое находится справа, и присваивает результат переменной. Это выражение может быть достаточно сложным и включать в себя любые другие переменные: ```js //+ run var a = 1; var b = 2; *!* a = b + a + 3; // (*) */!* alert(a); // 6 ``` В строке `(*)` сначала произойдет вычисление, использующее текущее значение `a` (т.е. `1`), после чего результат перезапишет старое значение `a`. **Возможно присваивание по цепочке:** ```js //+ run var a, b, c; *!* a = b = c = 2 + 2; */!* alert(a); // 4 alert(b); // 4 alert(c); // 4 ``` Такое присваивание работает справа-налево, то есть сначала вычислятся самое правое выражение `2+2`, присвоится в `c`, затем выполнится `b = c` и, наконец, `a = b`. [smart header="Оператор `\"=\"` возвращает значение"] Все операторы возвращают значение. Вызов `x = выражение` записывает выражение в `x`, а затем возвращает его. Благодаря этому присваивание можно использовать как часть более сложного выражения: ```js //+ run var a = 1; var b = 2; *!* var c = 3 - (a = b + 1); */!* alert(a); // 3 alert(c); // 0 ``` В примере выше результатом `(a = b + 1)` является значение, которое записывается в `a` (т.е. `3`). Оно используется для вычисления `c`. Забавное применение присваивания, не так ли? Знать, как это работает -- стоит обязательно, а вот писать самому -- только если вы уверены, что это сделает код более читаемым и понятным. [/smart] ## Приоритет В том случае, если в выражении есть несколько операторов - порядок их выполнения определяется *приоритетом*. Из школы мы знаем, что умножение в выражении `2 * 2 + 1` выполнится раньше сложения, т.к. его *приоритет* выше, а скобки явно задают порядок выполнения. Но в JavaScript -- гораздо больше операторов, поэтому существует целая [таблица приоритетов](https://developer.mozilla.org/en/JavaScript/Reference/operators/operator_precedence). Она содержит как уже пройденные операторы, так и те, которые мы еще не проходили. В ней каждому оператору задан числовой приоритет. Тот, у кого число меньше -- выполнится раньше. Если приоритет одинаковый, то порядок выполнения -- слева направо. Отрывок из таблицы:
.........
5умножение`*`
5деление`/`
6сложение`+`
6вычитание`-`
17присвоение`=`
.........
Посмотрим на таблицу в действии. В выражении `x = 2 * 2 + 1` есть три оператора: присвоение `=`, умножение `*` и сложение `+`. Приоритет умножения `*` равен `5`, оно выполнится первым, затем произойдёт сложение `+`, у которого приоритет `6`, и после них -- присвоение `=`, с приоритетом 17. ## Инкремент/декремент: ++, -- Одной из наиболее частых операций в JavaScript, как и во многих других языках программирования, является увеличение или уменьшение переменной на единицу. Для этого существуют даже специальные операторы: [warn] Инкремент/декремент можно применить только к переменной. Код `5++` даст ошибку. [/warn] Вызывать эти операторы можно не только после, но и перед переменной: `i++` (называется "постфиксная форма") или `++i` ("префиксная форма"). Обе эти формы записи делают одно и то же: увеличивают на `1`. Тем не менее, между ними существует разница. Она видна только в том случае, когда мы хотим не только увеличить/уменьшить переменную, но и использовать результат в том же выражении. Например: ```js //+ run var i = 1; var a = ++i; // (*) alert(a); // *!*2*/!* ``` В строке `(*)` вызов `++i` увеличит переменную, а *затем* вернёт ее значение в `a`. **То есть, в `a` попадёт значение `i` *после* увеличения**. **Постфиксная форма `i++` отличается от префиксной `++i` тем, что возвращает старое значение, бывшее до увеличения.** В примере ниже в `a` попадёт старое значение `i`, равное `1`: ```js //+ run var i = 1; var a = i++; // (*) alert(a); // *!*1*/!* ``` **Инкремент/декремент можно использовать в любых выражениях.** При этом он имеет более высокий приоритет и выполняется раньше, чем арифметические операции: ```js //+ run var i = 1; alert( 2 * ++i ); // 4 ``` ```js //+ run var i = 1; alert( 2 * i++ ); // 2, выполнился раньше но значение вернул старое ``` При этом, нужно с осторожностью использовать такую запись, потому что при чтении кода зачастую неочевидно, что переменая увеличивается. Три строки -- длиннее, зато нагляднее: ```js //+ run var i = 1; alert( 2 * i ); i++; ``` ## Побитовые операторы Побитовые операторы рассматривают аргументы как 32-разрядные целые числа и работают на уровне их внутреннего двоичного представления. Эти операторы не являются чем-то специфичным для JavaScript, они поддерживаются в большинстве языков программирования. Поддерживаются следующие побитовые операторы: Вы можете более подробно почитать о них в отдельной статье [](/bitwise-operators). ## Вызов операторов с присваиванием Часто нужно применить оператор к переменной и сохранить результат в ней же, например: ```js var n = 2; n = n + 5; n = n * 2; ``` Эту запись можно укоротить при помощи совмещённых операторов: +=, -=, *=, /=, >>=, <<=, >>>=, &=, |=, ^=. Вот так: ```js //+ run var n = 2; n += 5; // теперь n=7 (работает как n = n + 5) n *= 2; // теперь n=14 (работает как n = n * 2) alert(n); // 14 ``` Все эти операторы имеют в точности такой же приоритет, как обычное присваивание, то есть выполняются после большинства других операций. ## Оператор запятая Запятая тоже является оператором. Ее можно вызвать явным образом, например: ```js //+ run *!* a = (5, 6); */!* alert(a); ``` Запятая позволяет перечислять выражения, разделяя их запятой `','`. Каждое из них -- вычисляется и отбрасывается, за исключением последнего, которое возвращается. Запятая -- единственный оператор, приоритет которого ниже присваивания. В выражении `a = (5,6)` для явного задания приоритета использованы скобки, иначе оператор `'='` выполнился бы до запятой `','`, получилось бы `(a=5), 6`. Зачем же нужен такой странный оператор, который отбрасывает значения всех перечисленных выражений, кроме последнего? Обычно он используется в составе более сложных конструкций, чтобы сделать несколько действий в одной строке. Например: ```js // три операции в одной строке for (*!*a = 1, b = 3, c = a*b*/!*; a < 10; a++) { ... } ``` Такие трюки используются во многих JavaScript-фреймворках для укорачивания кода.