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
分組運算子可以更改任何運算子的運算子優先順序,因為它具有最高的運算子優先順序。
廣告