Javascript 简明教程
JavaScript - Operator Precedence
在 Javascript 中, operator precedence 确保了在单个表达式包含多个运算符时,执行运算符的优先级。因此,无论哪个表达式具有较高的优先级,编译器都会先对它执行其他运算符,然后执行具有较低优先级的运算符。
In JavaScript, operator precedence ensures the priority of the operators to be executed when a single expression contains multiple operators. So, whatever expressions have higher priority, the compiler executes it first over other operators and then executes the operators with the lower precedence.
每当你使用只有 1 或 2 个操作符编写任何 Javascript 表达式时,就可以轻松理解该表达式的输出。但是当表达式包含多个运算符时,你应该了解运算符优先级概念才能正确评估表达式。
Whenever you write any JavaScript expression with only 1 or 2 operators, you can easily understand the output of the expression. But when the expression contains multiple operators, you should know the concept of operator precedence to evaluate the expression correctly.
运算符优先级最好的例子是,在传统数学中,乘法运算符的优先级高于加法或减法运算符。因此,如果任何数学表达式同时包含乘法和加法运算符,则需要首先执行乘法。
The best example of operator precedence is that in traditional mathematics, the multiplication operator has higher precedence over the addition or subtraction operator. So, if any mathematical expression contains the multiplication and addition of both operators, you need to perform the multiplication first.
Associativity
关联性这一术语是指编译器在求解表达式时应该遵循的方向。在许多情况下,运算符有相同的优先级。在这种情况中,编译器应该先执行哪一个操作会出现歧义。因此,编译器会借助关联性。它可以从左到右,也可以从右到左。
The term associativity refers to the direction compiler should follow while evaluating the expression. In many situations, operators have the same precedence. In such cases, ambiguity occurs that which operation the compiler should perform first. So, the compiler takes the help of associativity. It can be from left to right or right to left.
例如,我们需要执行以下表达式。
For example, we need to execute the below expression.
let res = 50/5*2;
-
Considering the above expression as (50/5) * 2 gives 20 as an output.
-
Evaluating the expression like 50/ (5*2) gives the 5 as a resultant value.
为了解决上述歧义,编译器使用关联性规则。除法和乘法运算符的关联性是从左到右。因此,它将表达式求值为 (50 / 5) * 2。
To resolve the above ambiguity, the compiler uses the associativity rule. The associativity for the division and multiplication operator is from left to right. So, it evaluates the expression as (50 / 5) * 2.
赋值运算符具有从右到左的关联性。考虑以下赋值表达式。
The assignment operator has right-to-left associativity. Consider the below assignment expression.
P = q = 90;
在上述表达式中,90 赋值给 q,q 变量的值赋值给 p。
In the above expression, 90 is assigned to the q, and the value of the q variable is assigned to the p.
简而言之,JavaScript 编译器根据运算符优先级求解表达式,当多个运算符具有相同的优先级时,它会使用关联性规则。
In short, the JavaScript compiler evaluates the expression based on the operator precedence, and when multiple operators have the same precedence, it uses the associativity rule.
Operator Precedence Table
下表包含运算符、其描述、关联性方向和一个简短示例。
The below table contains the operator, its description, associativity direction, and a short example.
Operator Precedence |
Operator |
Description |
Associativity |
Example |
1 |
() |
Grouping |
L → R |
(expression) |
2 |
. |
Member of object |
L → R |
Object_name.property |
2 |
() |
Function call |
L → R |
Demo() |
2 |
new |
To create objects |
R → L |
New test() |
2 |
[] |
Member of object |
L → R |
Object["property"] |
3 |
— |
Postfix decrement |
- |
p--; |
3 |
++ |
Postfix increment |
- |
p++ |
4 |
— |
Prefix decrement |
R → L |
--p; |
4 |
++ |
Prefix increment |
R → L |
++p; |
4 |
typeof |
To get the variable type |
R → L |
typeof a; |
4 |
! |
Logical not |
R → L |
!a; |
4 |
~ |
Bitwise not |
R → L |
~p |
4 |
- |
Unary minus |
R → L |
-p |
4 |
+ |
Unary plus |
R → L |
+p |
4 |
delete |
To delete object property |
R → L |
Delete arr[0] |
4 |
void |
Evaluates void |
R → L |
Void(1) |
5 |
** |
Exponentiation operator |
R → L |
p ** q |
6 |
* |
Multiplication |
L → R |
p * q |
6 |
/ |
Division |
L → R |
p / q |
6 |
% |
modulo |
L → R |
p % q |
7 |
+ |
Addition or plus operator |
L → R |
p + q |
7 |
- |
Subtraction operator |
L → R |
p - q |
8 |
<< |
Left shift |
L → R |
p << 2 |
8 |
>> |
Signed right shift |
L → R |
p >> 2 |
8 |
>>> |
Unsigned right shift |
L → R |
p >>> 2 |
9 |
in |
Property in object |
L → R |
x in y |
9 |
instanceof |
Instance of object |
L → R |
p instanceof Object |
9 |
< |
Less than |
L → R |
p < q |
9 |
⇐ |
Less than or equal to |
L → R |
p ⇐ q |
9 |
> |
Greater than |
L → R |
p > q |
9 |
>= |
Greater than or equal to |
L → R |
p >= q |
10 |
== |
Equality |
L → R |
p == q |
10 |
!= |
Inequality |
L → R |
p != q |
10 |
=== |
Strict equality |
L → R |
p === q |
10 |
!== |
Strict inequality |
L → R |
p !== q |
11 |
& |
Bitwise AND |
L → R |
p & q |
12 |
^ |
Bitwise XOR |
L → R |
p ^ q |
13 |
Bitwise OR |
L → R |
||
p |
q |
14 |
&& |
Logical AND |
L → R |
p && q |
15 |
||
Logical OR |
L → R |
p |
||
q |
16 |
?? |
Nullish Coalescing |
R → L |
p ?? q |
17 |
= |
Assignment |
R → L |
p = q |
17 |
: |
Colon assignment |
R → L |
p : q |
17 |
+= |
Addition assignment |
R → L |
p += q |
17 |
-= |
Subtraction assignment |
R → L |
p -= q |
17 |
*= |
Multiplication assignment |
R → L |
p *= q |
17 |
/= |
Division assignment |
R → L |
p /= q |
17 |
%= |
Modulo assignment |
R → L |
p %= q |
17 |
**= |
Exponentiation assignment |
R → L |
p **= q |
17 |
<⇐ |
Left shift assignement |
R → L |
p <⇐ q |
17 |
>>= |
Right shift assignment |
R → L |
p >>= q |
17 |
>>>= |
Unsigned right shift assignment |
R → L |
p >>>= q |
17 |
&= |
Bitwise AND assignment |
R → L |
p &= q |
17 |
^= |
Bitwise XOR assignment |
R → L |
p ^= q |
17 |
= |
Bitwise OR assignment |
|
R → L |
p |
= q |
17 |
&&= |
Logical AND assignment |
R → L |
p &&= q |
17 |
|
= |
Logical OR assignement |
R → L |
p |
|
= q |
17 |
⇒ |
Arrow operator |
|
- |
(a, b )⇒ { // function code} |
17 |
… |
Spread operator |
- |
[… arr] |
18 |
yield |
Pause / Resume |
R → L |
yield p; |
19 |
, |
Comma operator |
Examples
让我们通过简单的示例来理解运算符优先级。
Let’s understand the operator precedence via simple examples.
Example
在下面的示例中,第一个表达式包含优先级相同的除法、取模和乘法运算符。因此,编译器将使用关联性规则,即乘法、除法和取模运算符从左到右。
In the example below, the first expression contains the division, modulo, and multiplication operators with the same precedence. So, the compiler will use the associativity rule, which is left to right for multiplication, division, and modulo operator.
因此,它将 30 除以 15,取 (30/15) 对 3 的模,并将 ((30/15)%3) 与 2 相乘。
So, it divides the 30 by 15, takes modulo of (30/15) with 3, and multiples the ((30/15)%3) with 2.
在第二个表达式中,指数运算符具有从右到左的关联性。因此,它将表达式求值为与 (2 8 (3 * 2)) 相同。
In the second expression, the exponentiation operator has right-to-left associativity. So, it evaluates the expression same as (2 8 (3 * 2)).
<html>
<body>
<div id = "output"></div>
<script>
const first = 30 / 15 % 3 * 2;
const second = 2 ** 3 ** 2;
document.getElementById("output").innerHTML =
"The value of first expression is : " + first + "<br>" +
"The value of second expression is : " + second;
</script>
</body>
</html>
Output
它将产生以下结果 −
It will produce the following result −
The value of first expression is : 4
The value of second expression is : 512
Example
此代码演示了如何使用分组运算符 () 来更改运算符优先级。在以下代码中,我们使用了与上述代码中相同表达式,但我们更改了运算符优先级。
This code demonstrates that you can use the grouping operator () to change the operator precedence. In the below code, we have taken the same expressions which we have taken in the above code, but we change the operator precedence.
在第一个表达式中,我们首先取模,然后将结果值乘以 2。因此,我们得 0,并将 30 除以 0,返回无穷大。
In the first expression, first, we take modulo and multiply the resultant value with 2. So, we get 0 and divide 30 by 0, returning infinity.
在第二个表达式中,第一个表达式计算 (2 * 3) 和 (8 * 2),等于 64。
In the second expression, the first expression evaluates the (2 * 3) and (8 * 2), which is equal to 64.
<html>
<body>
<div id = "output"></div>
<script>
const first = 30 / ((15 % 3) * 2);
const second = (2 ** 3) ** 2;
document.getElementById("output").innerHTML =
"The value of first expression is : " + first + "<br>" +
"The value of second expression is : " + second;
</script>
</body>
</html>