Операторы JavaScript | Приоритет операторов
Оператор – это символ(ы) или ключевое слово, благодаря которому производятся некоторые виды вычислений с участием одного или нескольких значений. Значения, располагающиеся слева и справа от оператора, называются операндами. Оператор с одним операндом называется унарным, с двумя – бинарным, с тремя – тернарным.
Операторы могут автоматически преобразовывать типы своих операндов по мере необходимости. Например, оператор умножения *
ожидает получить числа, поэтому выражение "2" * "3"
считается вполне допустимым благодаря тому, что интерпретатор выполнит неявное преобразование строк в числа.
Приоритет операторов
Приоритет оператора – это свойство оператора, влияющее на очерёдность его выполнения в выражении с несколькими различными операторами при отсутствии явного указания на порядок их вычисления. Операторы с более высоким приоритетом выполняются раньше операторов с более низким приоритетом.
В колонке
троеточием показано расположение операндов относительно оператора.
В колонке А
указана ассоциативность оператора. Ассоциативность — это порядок, в котором обрабатываются операторы с одинаковым приоритетом. Например, оператор вычитания имеет ассоциативность слева направо, поэтому следующие два выражения эквивалентны:
x - y - z (x - y) - z
Оператор присваивания имеет ассоциативность справа налево, поэтому следующие два выражения эквивалентны:
w = x = y = z w = (x = (y = z))
В колонке О
указано количество операндов.
В колонке Типы значений
перед стрелкой указаны ожидаемые типы операндов, а после стрелки тип возвращаемого значения.
lval (сокращение от left value) – левостороннее выражение. Это исторический термин, обозначающий выражение, которое может присутствовать слева от оператора присваивания. Левосторонними выражениями являются: переменные, свойства объектов и элементы массивов.
В таблице ниже операторы перечислены в порядке уменьшения приоритета, горизонтальные линии отделяют группы операторов с разным уровнем приоритета.
Оператор | Тип оператора | А | О | Типы значений |
---|---|---|---|---|
(…) | Группировка | отсутствует |
1 | любое→любое |
… . … … […] new … ( ) |
Оператор доступа Оператор доступа new (со списком аргументов) |
слева направо слева направо отсутствует |
2 2 1 |
lval, lval → любой lval, строка или число → любой конструктор → объект |
… ( ) new … |
Вызов функции new (без аргументов) |
слева направо справа налево |
1 1 |
функция → любой конструктор → объект |
… ++ … — |
Постфиксный инкремент Постфиксный декремент |
отсутствует отсутствует |
1 1 |
lval → число lval → число |
! … ~ … + … — … ++ … — … delete … typeof … void … |
Логическое НЕ (инверсия) Побитовое НЕ (инверсия) Унарный плюс Унарный минус Префиксный инкремент Префиксный декремент Удаление Определяет тип данных Возврат неопределённого значения |
справа налево справа налево справа налево справа налево справа налево справа налево справа налево справа налево справа налево |
1 1 1 1 1 1 1 1 1 |
любое → булево целое → целое число → число число → число lval → число lval → число lval → булево любое → строка любое → undefined |
… ** … … * … … / … … % … |
Возведение в степень Умножение Деление Деление с остатком |
справа налево слева направо слева направо |
2 2 2 2 |
число, число → число число, число → число число, число → число число, число → число |
… + … … — … … + … |
Сложение Вычитание Конкатенация |
слева направо слева направо слева направо |
2 2 2 |
число, число → число число, число → число строка, строка → строка |
… << … … >> … … >>> … |
Сдвиг битов влево Сдвиг битов вправо с сохранением знака Сдвиг битов вправо с заполнением нулями |
слева направо слева направо слева направо |
2 2 2 |
целое, целое → целое целое, целое → целое целое, целое → целое |
… < … … <= … … > … … >= … … in … … instanceof … |
Меньше чем Меньше или равно Больше чем Больше или равно Проверка наличия свойства Проверка на принадлежность к данному типу |
слева направо слева направо слева направо слева направо слева направо слева направо |
2 2 2 2 2 2 |
число, число → булево число, число → булево число, число → булево число, число → булево строка, объект → булево объект, конструктор → булево |
… == … … != … … === … … !== … |
Равно Не равно Строго равно Строго не равно |
слева направо слева направо слева направо слева направо |
2 2 2 2 |
любое, любое → булево любое, любое → булево любое, любое → булево любое, любое → булево |
… & … | Побитовое И | слева направо | 2 | целое, целое → целое |
… ^ … | Побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ | слева направо | 2 | целое, целое → целое |
… | … | Побитовое ИЛИ | слева направо | 2 | целое, целое → целое |
… && … | Логическое И | слева направо | 2 | любое, любое → любое |
… || … | Логическое ИЛИ | слева направо | 2 | любое, любое → любое |
… ? … : … | Тернарный оператор | справа налево | 3 | булево, любое, любое → любое |
… = … … += … … -= … … **= … … *= … … /= … … %= … … <<= … … >>= … … >>>= … … &= … … ^= … … |= … |
Присваивание Операция с присваиванием Операция с присваиванием Операция с присваиванием Операция с присваиванием Операция с присваиванием Операция с присваиванием Операция с присваиванием Операция с присваиванием Операция с присваиванием Операция с присваиванием Операция с присваиванием Операция с присваиванием |
справа налево справа налево справа налево справа налево справа налево справа налево справа налево справа налево справа налево справа налево справа налево справа налево справа налево |
2 2 2 2 2 2 2 2 2 2 2 2 2 |
lval, любое → любое lval, любое → любое lval, любое → любое lval, любое → любое lval, любое → любое lval, любое → любое lval, любое → любое lval, любое → любое lval, любое → любое lval, любое → любое lval, любое → любое lval, любое → любое lval, любое → любое |
yield … yield* … |
yield yield* |
справа налево справа налево |
1 1 |
|
… … | Расширение | отсутствует | 1 | |
… , … | Запятая | слева направо | 2 | любое, любое → любое |
Операторы
Операторы, выражения и инструкции JavaScript — это основные строительные кирпичики программ. С их помощью можно манипулировать значениями, сравнивать их между собой, производить вычисления и решать множество прочих задач. В этом уроке вы познакомитесь с тем, как работают операторы и узнаете о том, как использовать их с максимальной пользой.
Знакомство с операторами
Для работы с данными JavaScript поддерживает все стандартные операторы, большинство которых есть и в других языках программирования. Операторы варьируются от математических и поразрядных до операторов отношения и сравнения. Опepaтopы в JavaScript уникальны в том смысле, что их можно задействовать с самыми различными значениями, включая строки, числа, логические значения и даже объекты.
Операторы предназначены для составления выражений. Оператор применяется к одному или двум данным, которые называются операндами или аргументами оператора.
Например, в следующем примере знак + (плюс) – это оператор, объединяющий два операнда в одно выражение:
Операторы, работающие с единственным операндом, называются унарными. Это самые простые операторы в JavaScript.
Оператор - (минус), в следующем примере, представляет собой унарный оператор, выполняющий смену знака для операнда 3:
Большинство JavaScript-операторов объединяют два выражения в одно, более сложное. Таким образом, эти операторы работают с двумя операндами и называются бинарными:
Тип операндов
Работая с выражениями, следует уделять внимание типам операндов, передаваемых операторам, а также типам данных, возвращаемых этими операторами.
Некоторые операторы могут взаимодействовать с операндами только определенного типа. Например, в JavaScript является недопустимым умножение строк:
Интерпретатор JavaScript, если возможно, преобразовывает рассматриваемое выражение в требуемый тип, поэтому следующее выражение вполне допустимо:
Существуют операторы которые ведут себя по-разному в зависимости от типа передаваемых им операндов. Например, оператор сложения +, который, как правило, осуществляет сложение числовых операндов, выполняет конкатенацию («склеивание») строк. Результатом выполнения этой операции является строка, состоящая из строковых значений операндов:
Кроме того, если оператору сложения передать одну строку и одно число, то число будет преобразовано в строку и выполнится конкатенацию двух полученных строк. Причем не важно, справа или слева находится операнд-строка, в любом случае нестроковый аргумент будет преобразован в строку:
На заметку: Если при сложении хотя бы один операнд является строкой, то второй будет также преобразован к строке.
Операторы не всегда возвращают значения того же типа, к которому принадлежат их аргументы. Например, операторы сравнения (меньше, больше, равно и т. д.) принимают операнды различных типов, однако всегда возвращают выражение логического типа:
Приоритет операторов
В случае, когда в выражении используется несколько операторов – порядок их выполнения определяется приоритетом. Операторы с более высоким приоритетом выполняются раньше операторов с более низким приоритетом. Рассмотрим следующий пример:
Из школьного курса математики мы знаем, что приоритет оператора * (умножение) выше, чем сложения, поэтому сначала 4
будет умножено на 5
. Затем полученный результат будет разделен на 2
, так как приоритет оператора / (деление) выше, чем сложения. Далее, к полученному результу будет добавлено значение 7
. И, наконец, оператор присваивания = имеет наименьший приоритет, поэтому присваивание выполняется после завершения всех операций в правой части. В результате переменной sum
будет присвоено значение 17
.
Приоритет операторов может быть переопределен с помощью скобок. Для того, чтобы сложение в предыдущем примере выполнялось раньше, надо написать:
В этом примере сначала будет выполнено сложение (7 + 4)
, а затем полученный результат будет умножен на 5
и разделен на 2
. Операторы умножения и деления имеют одинаковый приоритет, поэтому они выполняются слева направо, то есть в порядке их следования.
В таблице ниже операторы перечислены в порядке уменьшения от наивысшего (20) до самого низкого (0) приоритета.
Применение: Если в коде содержится два и более операторов с одинаковым приоритетом, то очередность их выполнения определяется их ассоциативностью — характеристикой оператора, определяющей направление вычислений: слева направо или справа налево.
Итоги
- Опepaтopы в JavaScript уникальны в том смысле, что их можно задействовать с самыми различными значениями, включая строки, числа, логические значения и даже объекты.
- Операторы предназначены для составления выражений. Оператор применяется к одному или двум данным, которые называются операндами.
- Приоритет операторов определяет очередность их выполнения в выражении. Все операторы делятся на группы с различными уровнями приоритета от 0 до 20.
Приоритет оператора с тернарным оператором Javascript
Я знаю, что это очень старый вопрос, но я не удовлетворен ни одним из ответов, поскольку все они кажутся неполными. Итак, мы снова начинаем с первых принципов:
Общая цель пользователя:
Резюмируя код: «я хочу добавить имя класса error
в строку, необязательно с начальным пробелом, если в строке уже есть имена классов.
Простейшее решение
Как отметил Коби, 5 лет назад наличие лидирующего пространства в именах классов не вызовет никаких проблем ни с одним известным браузером, поэтому самым коротким правильным решением на самом деле будет:
h.className += ' error';
Это должно было стать настоящим ответом на реальную проблему .
Как бы то ни было, но вопросы были заданы…
1) Почему это сработало?
h.className += h.className ? ' error' : 'error'
Условный / тернарный оператор работает как оператор if, который присваивает результат своих путей true
или false
переменной.
Таким образом, этот код работал, потому что он оценивается просто как:
if (h.className IS NOT null AND IS NOT undefined AND IS NOT '')
h.className += ' error'
else
h.className += 'error'
2) а почему это сломалось?
h.className = h.className + h.className ? ' error' : 'error'
Вопрос гласит: «Это дает ошибку a[n] в моей консоли», которая может ввести вас в заблуждение, думая, что код не функционирует . На самом деле следующий код действительно выполняется без ошибок, но он просто возвращает «error», если строка не была пустой, и ‘error’, если строка была пустой и поэтому не соответствовала требованиям .
Этот код всегда приводит к строке, которая содержит только ' error'
или 'error'
, потому что он вычисляется в этот псевдокод:
if ((h.className + h.className) IS NOT null AND IS NOT undefined AND IS NOT '')
h.className = ' error'
else
h.className = 'error'
Причина этого заключается в том, что оператор сложения ( +
для простых людей) имеет более высокий «precedence» (6), чем условный/тернарный оператор (15). Я знаю, что цифры появляются задом наперед
Приоритет просто означает, что каждый тип оператора в языке вычисляется в определенном предопределенном порядке (а не только left-to-right).
Как изменить порядок оценки:
Теперь мы знаем, почему он не работает, вам нужно знать, как заставить его работать.
Некоторые другие ответы говорят об изменении приоритета, но вы не можете этого сделать . Приоритет жестко привязан к языку. Это просто фиксированный набор правил… Однако вы можете изменить порядок оценки …
Инструментом в нашем наборе инструментов, который может изменить порядок оценки , является оператор группировки (он же скобки). Он делает это, гарантируя, что выражения в скобках вычисляются перед операциями вне скобок. Это все, что они делают, но и этого достаточно.
Скобки работают просто потому, что они (операторы группировки) имеют более
Просто добавляя скобки, вы изменяете порядок вычисления , чтобы убедиться, что условный тест выполняется первым, перед простой конкатенацией строк:
h.className = h.className + (h.className ? ' error' : 'error')
Теперь я оставлю этот ответ rust невидимым среди других 🙂
Приоритеты операторов | Конспект JS-course
Приоритеты операторов | Конспект JS-course- Конспект JS-course
- Конспект JS-course
- 1. Операторы, приведение типов, ветвление
- 2. Массивы, объекты, циклы
- 2.1. JavaScript Garden. Объекты
- 2.2. JavaScript Garden. Массивы
- 3. Циклы, массивы. Почитать про методы
- 3.1. Конспект по массивам, объектам, структурам данных
- 3.2. Конспект. Методы
- 4. Функции
- 5. Функции и области видимости
- 6. Функции. Продолжение
- 7. Функции, методы, наследование
- 8. Классы, наследование
- 9. Массивы, чтение
- 10. DOM (document object model)
- 11. Читаем про html, css
- 12. Верстка
- 13. Верстка
- 14. Верстка
- 15. DOM
- 16. DOM events
Приоритет оператора с троичным оператором Javascript
Я знаю, что это очень старый вопрос, но я не на 100% доволен ни одним из ответов, поскольку все они кажутся неполными. Итак, здесь мы снова идем от первых принципов:
Общая цель пользователя:
Обобщение кода: «Я хочу добавить имя класса error
в строку, необязательно с начальным пробелом, если в строке уже есть имена классов».
Самое простое решение
Как отметил Коби, 5 лет назад наличие лидирующего пробела в именах классов не вызывало проблем с любыми известными браузерами, поэтому самое короткое правильное решение на самом деле было бы:
h.className += ' error';
Это должно было быть реальным ответом на актуальную проблему .
Как бы то ни было, задаваемые вопросы были …
1) Почему это работает?
h.className += h.className ? ' error' : 'error'
Условный / троичный оператор работает как оператор if, который присваивает переменным результат его true
или false
путей.
Так что код работал, потому что он оценивается просто как:
if (h.className IS NOT null AND IS NOT undefined AND IS NOT '')
h.className += ' error'
else
h.className += 'error'
2) и почему это сломалось?
h.className = h.className + h.className ? ' error' : 'error'
Вопрос гласит: «это приводит к ошибке [n] в моей консоли», что может ввести вас в заблуждение, полагая, что код не работает . Фактически следующий код выполняется без ошибок , но он просто возвращает «ошибку», если строка не была пустой, и «ошибку», если строка была пустой и поэтому не отвечала требованиям .
Этот код всегда приводит к строке, которая содержит только ' error'
или 'error'
потому что он оценивает этот псевдокод:
if ((h.className + h.className) IS NOT null AND IS NOT undefined AND IS NOT '')
h.className = ' error'
else
h.className = 'error'
Причина этого заключается в том, что оператор сложения ( +
к обычному народу) имеет более высокий «приоритет» (6), чем условный / троичный оператор (15). Я знаю, что цифры появляются в обратном направлении
Приоритет просто означает, что каждый тип оператора в языке оценивается в определенном предопределенном порядке (а не только слева направо).
Как изменить порядок оценки:
Теперь мы знаем, почему это не помогает, вам нужно знать, как заставить это работать.
Некоторые другие ответы говорят об изменении приоритета , но вы не можете . Приоритет запрограммирован в язык. Это просто фиксированный набор правил … Однако вы можете изменить порядок оценки …
Инструментом в нашем наборе инструментов, который может изменить порядок оценки, является оператор группировки (он же скобки). Это достигается за счет того, что выражения в скобках вычисляются перед операциями вне скобок. Это все, что они делают, но этого достаточно.
Скобки работают просто потому, что они (операторы группировки) имеют более высокий приоритет, чем все другие операторы («теперь есть уровень 0»).
Просто добавляя скобки, вы изменяете порядок вычисления, чтобы убедиться, что сначала выполняется условный тест перед простой конкатенацией строк:
h.className = h.className + (h.className ? ' error' : 'error')
Теперь я оставлю этот ответ на ржавчину невидимым среди других 🙂