JavaScript - 运算符优先级



在 JavaScript 中,**运算符优先级**确保在单个表达式包含多个运算符时,运算符的执行优先级。因此,无论哪个表达式具有更高的优先级,编译器都会先执行它,然后再执行优先级较低的运算符。

当您编写任何仅包含 1 或 2 个运算符的 JavaScript 表达式时,您可以轻松理解表达式的输出。但是,当表达式包含多个运算符时,您应该了解运算符优先级的概念才能正确评估表达式。

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

结合性

术语“结合性”指的是编译器在评估表达式时应遵循的方向。在许多情况下,运算符具有相同的优先级。在这种情况下,会产生歧义,即编译器应该先执行哪个操作。因此,编译器会借助结合性。它可以是从左到右或从右到左。

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

let res = 50/5*2;
  • 将上述表达式视为 (50/5) * 2 会得到 20 作为输出。

  • 将表达式评估为 50/ (5*2) 会得到 5 作为结果值。

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

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

P = q = 90;

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

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

运算符优先级表

下表包含运算符、其描述、结合性方向和简短示例。

运算符优先级 运算符 描述 结合性 示例
1 () 分组 L -> R (表达式)
2 . 对象成员 L -> R Object_name.property
2 () 函数调用 L -> R Demo()
2 new 创建对象 R -> L New test()
2 [] 对象成员 L -> R Object["property"]
3 -- 后缀递减 - p--;
3 ++ 后缀递增 - p++
4 -- 前缀递减 R -> L --p;
4 ++ 前缀递增 R -> L ++p;
4 typeof 获取变量类型 R -> L typeof a;
4 ! 逻辑非 R -> L !a;
4 ~ 按位非 R -> L ~p
4 - 一元负号 R -> L -p
4 + 一元正号 R -> L +p
4 delete 删除对象属性 R -> L Delete arr[0]
4 void 评估 void R -> L Void(1)
5 ** 幂运算符 R -> L p ** q
6 * 乘法 L -> R p * q
6 / 除法 L -> R p / q
6 % 取模 L -> R p % q
7 + 加法或加号运算符 L -> R p + q
7 - 减法运算符 L -> R p - q
8 << 左移 L -> R p << 2
8 >> 带符号右移 L -> R p >> 2
8 >>> 无符号右移 L -> R p >>> 2
9 in 对象中的属性 L -> R x in y
9 instanceof 对象的实例

L -> R p 是 Object 的实例
9 < 小于 L -> R p < q
9 <= 小于或等于 L -> R p <= q
9 > 大于 L -> R p > q
9 >= 大于或等于 L -> R p >= q
10 == 相等 L -> R p == q
10 != 不相等 L -> R p != q
10 === 严格相等 L -> R p === q
10 !== 严格不相等 L -> R p !== q
11 & 按位与 L -> R p & q
12 ^ 按位异或 L -> R p ^ q
13 | 按位或 L -> R p | q
14 && 逻辑与 L -> R p && q
15 || 逻辑或 L -> R p || q
16 ?? 空值合并 R -> L p ?? q
17 = 赋值 R -> L p = q
17 : 冒号赋值 R -> L p : q
17 += 加法赋值 R -> L p += q
17 -= 减法赋值 R -> L p -= q
17 *= 乘法赋值 R -> L p *= q
17 /= 除法赋值 R -> L p /= q
17 %= 取模赋值 R -> L p %= q
17 **= 指数赋值 R -> L p **= q
17 <<= 左移赋值 R -> L p <<= q
17 >>= 右移赋值 R -> L p >>= q
17 >>>= 无符号右移赋值 R -> L p >>>= q
17 &= 按位与赋值 R -> L p &= q
17 ^= 按位异或赋值 R -> L p ^= q
17 |= 按位或赋值 R -> L p |= q
17 &&= 逻辑与赋值 R -> L p &&= q
17 ||= 逻辑或赋值 R -> L p ||= q
17 => 箭头运算符 - (a, b )=> { // 函数代码}
17 扩展运算符 - [… arr]
18 yield 暂停/恢复 R -> L yield p;
19 , 逗号运算符 L -> R (10, 20, 30)

示例

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

示例

在下面的示例中,第一个表达式包含除法、取模和乘法运算符,它们具有相同的优先级。因此,编译器将使用结合性规则,对于乘法、除法和取模运算符,该规则是从左到右。

所以,它将 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>

输出

它将产生以下结果:

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

示例

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

在第一个表达式中,首先,我们取模并将结果值乘以 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>

输出

The value of first expression is : Infinity
The value of second expression is : 64
分组运算符可以更改任何运算符的运算符优先级,因为它具有最高的运算符优先级。
广告