Javascript 简明教程

JavaScript - Operator Precedence

在 Javascript 中, operator precedence 确保了在单个表达式包含多个运算符时,执行运算符的优先级。因此,无论哪个表达式具有较高的优先级,编译器都会先对它执行其他运算符,然后执行具有较低优先级的运算符。

每当你使用只有 1 或 2 个操作符编写任何 Javascript 表达式时,就可以轻松理解该表达式的输出。但是当表达式包含多个运算符时,你应该了解运算符优先级概念才能正确评估表达式。

运算符优先级最好的例子是,在传统数学中,乘法运算符的优先级高于加法或减法运算符。因此,如果任何数学表达式同时包含乘法和加法运算符,则需要首先执行乘法。

Associativity

关联性这一术语是指编译器在求解表达式时应该遵循的方向。在许多情况下,运算符有相同的优先级。在这种情况中,编译器应该先执行哪一个操作会出现歧义。因此,编译器会借助关联性。它可以从左到右,也可以从右到左。

例如,我们需要执行以下表达式。

let res = 50/5*2;
  1. 将上述表达式看作 (50 / 5) * 2 得出 20 作为输出。

  2. 像 50 / (5 * 2) 这样评估表达式得出的结果值为 5。

为了解决上述歧义,编译器使用关联性规则。除法和乘法运算符的关联性是从左到右。因此,它将表达式求值为 (50 / 5) * 2。

赋值运算符具有从右到左的关联性。考虑以下赋值表达式。

P = q = 90;

在上述表达式中,90 赋值给 q,q 变量的值赋值给 p。

简而言之,JavaScript 编译器根据运算符优先级求解表达式,当多个运算符具有相同的优先级时,它会使用关联性规则。

Operator Precedence Table

下表包含运算符、其描述、关联性方向和一个简短示例。

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

要获取变量类型

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

小于或等于

L → R

p ⇐ q

9

>

Greater than

L → R

p > q

9

>=

大于或等于

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 )⇒ { // 函数代码}

17

Spread operator

-

[… arr]

18

yield

Pause / Resume

R → L

yield p;

19

,

Comma operator

Examples

让我们通过简单的示例来理解运算符优先级。

Example

在下面的示例中,第一个表达式包含优先级相同的除法、取模和乘法运算符。因此,编译器将使用关联性规则,即乘法、除法和取模运算符从左到右。

因此,它将 30 除以 15,取 (30/15) 对 3 的模,并将 ((30/15)%3) 与 2 相乘。

在第二个表达式中,指数运算符具有从右到左的关联性。因此,它将表达式求值为与 (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

它将产生以下结果 −

The value of first expression is : 4
The value of second expression is : 512

Example

此代码演示了如何使用分组运算符 () 来更改运算符优先级。在以下代码中,我们使用了与上述代码中相同表达式,但我们更改了运算符优先级。

在第一个表达式中,我们首先取模,然后将结果值乘以 2。因此,我们得 0,并将 30 除以 0,返回无穷大。

在第二个表达式中,第一个表达式计算 (2 * 3) 和 (8 * 2),等于 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>

Output

The value of first expression is : Infinity
The value of second expression is : 64