From 98f82524f4679f084b85fa12a4475b63d202e729 Mon Sep 17 00:00:00 2001 From: allo Date: Thu, 6 Jan 2022 09:54:10 +0800 Subject: mv to .md for operator/precedence --- .../operators/operator_precedence/index.html | 487 --------------------- .../operators/operator_precedence/index.md | 487 +++++++++++++++++++++ 2 files changed, 487 insertions(+), 487 deletions(-) delete mode 100644 files/zh-cn/web/javascript/reference/operators/operator_precedence/index.html create mode 100644 files/zh-cn/web/javascript/reference/operators/operator_precedence/index.md (limited to 'files') diff --git a/files/zh-cn/web/javascript/reference/operators/operator_precedence/index.html b/files/zh-cn/web/javascript/reference/operators/operator_precedence/index.html deleted file mode 100644 index bb742caac7..0000000000 --- a/files/zh-cn/web/javascript/reference/operators/operator_precedence/index.html +++ /dev/null @@ -1,487 +0,0 @@ ---- -title: 运算符优先级 -slug: Web/JavaScript/Reference/Operators/Operator_Precedence -tags: - - 指南 - - JavaScript - - 优先级 -translation_of: Web/JavaScript/Reference/Operators/Operator_Precedence ---- -
{{jsSidebar("Operators")}}
- -

运算符的优先级决定了表达式中运算执行的先后顺序。优先级高的运算符会作为优先级低的运算符的操作符。

- -
{{EmbedInteractiveExample("pages/js/expressions-operatorprecedence.html")}}
- - -

优先级和结合性

- -

考虑由下面的表示法描述的表达式。其中,OP1 和 OP2 都是操作符的占位符。

- -
a OP1 b OP2 c
- -

如果 OP1OP2 具有不同的优先级(见下表),则优先级最高的运算符先执行,不用考虑结合性。观察乘法如何具有比加法更高的优先级并首先执行,即使加法是首先写入代码的。

- -
console.log(3 + 10 * 2);   // 输出 23
-console.log(3 + (10 * 2)); // 输出 23 因为这里的括号是多余的
-console.log((3 + 10) * 2); // 输出 26 因为括号改变了优先级
-
- -

左结合(左到右)相当于把左边的子表达式加上小括号 (a OP b) OP c,右结合(右到左)相当于 a OP (b OP c)。赋值运算符是右结合的,所以你可以这么写:

- -
a = b = 5; // 相当于 a = (b = 5);
-
- -

预期结果是 a 和 b 的值都会成为 5。这是因为赋值运算符的返回结果就是赋值运算符右边的那个值,具体过程是:首先 b 被赋值为 5,然后 a 也被赋值为 b = 5 的返回值,也就是 5。

- -

另一个例子是,只有幂运算符是右结合的,而其他算术运算符都是左结合的。有趣的是,无论结合性和优先级如何,求值顺序总是从左到右。

- - - - - - - - - - - - - - - - -
代码输出
-
-function echo(name, num) {
-    console.log("Evaluating the " + name + " side");
-    return num;
-}
-// 注意这里的除法运算符 (/)
-console.log(echo("left", 6) / echo("right", 2));
-
-
-
-Evaluating the left side
-Evaluating the right side
-3
-
-
-
-function echo(name, num) {
-    console.log("Evaluating the " + name + " side");
-    return num;
-}
-// 注意这里的幂运算符 (**)
-console.log(echo("left", 2) ** echo("right", 3));
-
-
-Evaluating the left side
-Evaluating the right side
-8
-
- -

当有多个具有相同优先级的运算符时,结合性的差异就会发挥作用。仅使用一个或多个不同优先级的运算符时,结合性不会影响输出,如上面的例子所示。在下面的示例中,观察使用多个相同运算符时结合性会如何影响输出。

- - - - - - - - - - - - - - - - - - - - -
代码输出
-
-function echo(name, num) {
-    console.log("Evaluating the " + name + " side");
-    return num;
-}
-// 注意这里的除法运算符 (/)
-console.log(echo("left", 6) / echo("middle", 2) / echo("right", 3));
-
-
-
-Evaluating the left side
-Evaluating the middle side
-Evaluating the right side
-1
-
-
-
-function echo(name, num) {
-    console.log("Evaluating the " + name + " side");
-    return num;
-}
-// 注意这里的幂运算符 (**)
-console.log(echo("left", 2) ** echo("middle", 3) ** echo("right", 2));
-
-
-
-Evaluating the left side
-Evaluating the middle side
-Evaluating the right side
-512
-
-
-
-function echo(name, num) {
-    console.log("Evaluating the " + name + " side");
-    return num;
-}
-// 注意这里左边和中间的被圆括号包围的求幂表达式
-console.log((echo("left", 2) ** echo("middle", 3)) ** echo("right", 2));
-
-
-Evaluating the left side
-Evaluating the middle side
-Evaluating the right side
-64
-
- -

观察上面的代码片段,6 / 3 / 2 与 - (6 / 3) / 2 是相同的,因为除法是左结合的。而幂运算符是右结合的,所以 2 ** 3 ** 2 与 - 2 ** (3 ** 2) 是相同的。因此,(2 ** 3) ** 2 会更改执行顺序,并导致输出上表中的 64。

- -

请记住,判断执行顺序的时候,优先级在结合性之前。所以,混合求除法和幂时,求幂会先于除法。例如, - 2 ** 3 / 3 ** 2 的结果是 0.8888888888888888,因为它相当于 - (2 ** 3) / (3 ** 2)

- -

分组和短路的注意事项

- -

在下表中,分组(Grouping)具有最高优先级。然而,这并不意味着总是优先对分组符号 ( … ) 内的表达式进行求值,尤其是涉及短路时。

- -

短路是条件求值的术语。例如,在表达式 - a && (b + c) 中,如果 a 为虚值({{Glossary("falsy")}}),那么即使 (b + c) 在圆括号中,也不会被求值。我们可以说逻辑或运算符(“OR”)是“短路的”。除了逻辑或运算符外,其他短路运算符还包括逻辑与(“AND”)、空值合并、可选链和条件(三元)运算符。下面有更多例子:

- -
a || (b * c);  // 首先对 `a` 求值,如果 `a` 为真值则直接返回 `a`
-a && (b < c);  // 首先对 `a` 求值,如果 `a` 为虚值则直接返回 `a`
-a ?? (b || c); // 首先对 `a` 求值,如果 `a` 不是 `null` 或 `undefined` 则直接返回 `a`
-a?.b.c;        // 首先对 `a` 求值,如果 `a` 是 `null` 或 `undefined` 则直接返回 `undefined`
-
- -

示例

- -
3 > 2 && 2 > 1
-// 返回 true
-
-3 > 2 > 1
-// 返回 false,因为 3 > 2 是 true,然后 true 会在比较运算符中
-// 被隐式转换为 1,因此 true > 1 会变为 1 > 1,结果是 false
-// 加括号可以更清楚:(3 > 2) > 1
-
- -

汇总表

- -

下面的表格将所有运算符按照优先级的不同从高(21)到低(1)排列。

- -

请注意,下表中故意不包含展开语法(Spread syntax) —— 原因可以引用Stack Overflow 上的一个回答,“展开语法不是一个运算符,因此没有优先级。它是数组字面量和函数调用(和对象字面量)语法的一部分。”

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
优先级运算符类型结合性运算符
21{{jsxref("Operators/Grouping", "分组", "", 1)}}n/a(不相关)( … )
20{{jsxref("Operators/Property_Accessors", "成员访问", "#Dot_notation", 1)}}从左到右… . …
{{jsxref("Operators/Property_Accessors", "需计算的成员访问", "#Bracket_notation", 1)}}从左到右… [ … ]
{{jsxref("Operators/new","new")}}(带参数列表)n/anew … ( … )
函数调用从左到右… ( )
可选链(Optional chaining)从左到右?.
19{{jsxref("Operators/new","new")}}(无参数列表)从右到左new …
18{{jsxref("Operators","后置递增","#Increment", 1)}}n/a… ++
{{jsxref("Operators","后置递减","#Decrement", 1)}}… --
17逻辑非 (!)从右到左! …
按位非 (~)~ …
一元加法 (+)+ …
一元减法 (-)- …
前置递增++ …
前置递减-- …
{{jsxref("Operators/typeof", "typeof")}}typeof …
{{jsxref("Operators/void", "void")}}void …
{{jsxref("Operators/delete", "delete")}}delete …
{{jsxref("Operators/await", "await")}}await …
16幂 (**)从右到左… ** …
15乘法 (*)从左到右… * …
除法 (/)… / …
取余 (%)… % …
14加法 (+)从左到右… + …
减法 (-)… - …
13按位左移 (<<)从左到右… << …
按位右移 (>>)… >> …
无符号右移 (>>>)… >>> …
12小于 (<)从左到右… < …
小于等于 (<=)… <= …
大于 (>)… > …
大于等于 (>=)… >= …
{{jsxref("Operators/in", "in")}}… in …
{{jsxref("Operators/instanceof", "instanceof")}}… instanceof …
11相等 (==)从左到右… == …
不相等 (!=)… != …
一致/严格相等 (===)… === …
不一致/严格不相等 (!==)… !== …
10按位与 (&)从左到右… & …
9按位异或 (^)从左到右… ^ …
8按位或 (|)从左到右… | …
7逻辑与 (&&)从左到右… && …
6逻辑或 (||)从左到右… || …
5空值合并 (??)从左到右… ?? …
4条件(三元)运算符从右到左… ? … : …
3赋值从右到左… = …
… += …
… -= …
… **= …
… *= …
… /= …
… %= …
… <<= …
… >>= …
… >>>= …
… &= …
… ^= …
… |= …
… &&= …
… ||= …
… ??= …
2{{jsxref("Operators/yield", "yield")}}从右到左yield …
{{jsxref("Operators/yield*", "yield*")}}yield* …
1逗号 / 序列从左到右… , …
\ No newline at end of file diff --git a/files/zh-cn/web/javascript/reference/operators/operator_precedence/index.md b/files/zh-cn/web/javascript/reference/operators/operator_precedence/index.md new file mode 100644 index 0000000000..bb742caac7 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/operators/operator_precedence/index.md @@ -0,0 +1,487 @@ +--- +title: 运算符优先级 +slug: Web/JavaScript/Reference/Operators/Operator_Precedence +tags: + - 指南 + - JavaScript + - 优先级 +translation_of: Web/JavaScript/Reference/Operators/Operator_Precedence +--- +
{{jsSidebar("Operators")}}
+ +

运算符的优先级决定了表达式中运算执行的先后顺序。优先级高的运算符会作为优先级低的运算符的操作符。

+ +
{{EmbedInteractiveExample("pages/js/expressions-operatorprecedence.html")}}
+ + +

优先级和结合性

+ +

考虑由下面的表示法描述的表达式。其中,OP1 和 OP2 都是操作符的占位符。

+ +
a OP1 b OP2 c
+ +

如果 OP1OP2 具有不同的优先级(见下表),则优先级最高的运算符先执行,不用考虑结合性。观察乘法如何具有比加法更高的优先级并首先执行,即使加法是首先写入代码的。

+ +
console.log(3 + 10 * 2);   // 输出 23
+console.log(3 + (10 * 2)); // 输出 23 因为这里的括号是多余的
+console.log((3 + 10) * 2); // 输出 26 因为括号改变了优先级
+
+ +

左结合(左到右)相当于把左边的子表达式加上小括号 (a OP b) OP c,右结合(右到左)相当于 a OP (b OP c)。赋值运算符是右结合的,所以你可以这么写:

+ +
a = b = 5; // 相当于 a = (b = 5);
+
+ +

预期结果是 a 和 b 的值都会成为 5。这是因为赋值运算符的返回结果就是赋值运算符右边的那个值,具体过程是:首先 b 被赋值为 5,然后 a 也被赋值为 b = 5 的返回值,也就是 5。

+ +

另一个例子是,只有幂运算符是右结合的,而其他算术运算符都是左结合的。有趣的是,无论结合性和优先级如何,求值顺序总是从左到右。

+ + + + + + + + + + + + + + + + +
代码输出
+
+function echo(name, num) {
+    console.log("Evaluating the " + name + " side");
+    return num;
+}
+// 注意这里的除法运算符 (/)
+console.log(echo("left", 6) / echo("right", 2));
+
+
+
+Evaluating the left side
+Evaluating the right side
+3
+
+
+
+function echo(name, num) {
+    console.log("Evaluating the " + name + " side");
+    return num;
+}
+// 注意这里的幂运算符 (**)
+console.log(echo("left", 2) ** echo("right", 3));
+
+
+Evaluating the left side
+Evaluating the right side
+8
+
+ +

当有多个具有相同优先级的运算符时,结合性的差异就会发挥作用。仅使用一个或多个不同优先级的运算符时,结合性不会影响输出,如上面的例子所示。在下面的示例中,观察使用多个相同运算符时结合性会如何影响输出。

+ + + + + + + + + + + + + + + + + + + + +
代码输出
+
+function echo(name, num) {
+    console.log("Evaluating the " + name + " side");
+    return num;
+}
+// 注意这里的除法运算符 (/)
+console.log(echo("left", 6) / echo("middle", 2) / echo("right", 3));
+
+
+
+Evaluating the left side
+Evaluating the middle side
+Evaluating the right side
+1
+
+
+
+function echo(name, num) {
+    console.log("Evaluating the " + name + " side");
+    return num;
+}
+// 注意这里的幂运算符 (**)
+console.log(echo("left", 2) ** echo("middle", 3) ** echo("right", 2));
+
+
+
+Evaluating the left side
+Evaluating the middle side
+Evaluating the right side
+512
+
+
+
+function echo(name, num) {
+    console.log("Evaluating the " + name + " side");
+    return num;
+}
+// 注意这里左边和中间的被圆括号包围的求幂表达式
+console.log((echo("left", 2) ** echo("middle", 3)) ** echo("right", 2));
+
+
+Evaluating the left side
+Evaluating the middle side
+Evaluating the right side
+64
+
+ +

观察上面的代码片段,6 / 3 / 2 与 + (6 / 3) / 2 是相同的,因为除法是左结合的。而幂运算符是右结合的,所以 2 ** 3 ** 2 与 + 2 ** (3 ** 2) 是相同的。因此,(2 ** 3) ** 2 会更改执行顺序,并导致输出上表中的 64。

+ +

请记住,判断执行顺序的时候,优先级在结合性之前。所以,混合求除法和幂时,求幂会先于除法。例如, + 2 ** 3 / 3 ** 2 的结果是 0.8888888888888888,因为它相当于 + (2 ** 3) / (3 ** 2)

+ +

分组和短路的注意事项

+ +

在下表中,分组(Grouping)具有最高优先级。然而,这并不意味着总是优先对分组符号 ( … ) 内的表达式进行求值,尤其是涉及短路时。

+ +

短路是条件求值的术语。例如,在表达式 + a && (b + c) 中,如果 a 为虚值({{Glossary("falsy")}}),那么即使 (b + c) 在圆括号中,也不会被求值。我们可以说逻辑或运算符(“OR”)是“短路的”。除了逻辑或运算符外,其他短路运算符还包括逻辑与(“AND”)、空值合并、可选链和条件(三元)运算符。下面有更多例子:

+ +
a || (b * c);  // 首先对 `a` 求值,如果 `a` 为真值则直接返回 `a`
+a && (b < c);  // 首先对 `a` 求值,如果 `a` 为虚值则直接返回 `a`
+a ?? (b || c); // 首先对 `a` 求值,如果 `a` 不是 `null` 或 `undefined` 则直接返回 `a`
+a?.b.c;        // 首先对 `a` 求值,如果 `a` 是 `null` 或 `undefined` 则直接返回 `undefined`
+
+ +

示例

+ +
3 > 2 && 2 > 1
+// 返回 true
+
+3 > 2 > 1
+// 返回 false,因为 3 > 2 是 true,然后 true 会在比较运算符中
+// 被隐式转换为 1,因此 true > 1 会变为 1 > 1,结果是 false
+// 加括号可以更清楚:(3 > 2) > 1
+
+ +

汇总表

+ +

下面的表格将所有运算符按照优先级的不同从高(21)到低(1)排列。

+ +

请注意,下表中故意不包含展开语法(Spread syntax) —— 原因可以引用Stack Overflow 上的一个回答,“展开语法不是一个运算符,因此没有优先级。它是数组字面量和函数调用(和对象字面量)语法的一部分。”

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
优先级运算符类型结合性运算符
21{{jsxref("Operators/Grouping", "分组", "", 1)}}n/a(不相关)( … )
20{{jsxref("Operators/Property_Accessors", "成员访问", "#Dot_notation", 1)}}从左到右… . …
{{jsxref("Operators/Property_Accessors", "需计算的成员访问", "#Bracket_notation", 1)}}从左到右… [ … ]
{{jsxref("Operators/new","new")}}(带参数列表)n/anew … ( … )
函数调用从左到右… ( )
可选链(Optional chaining)从左到右?.
19{{jsxref("Operators/new","new")}}(无参数列表)从右到左new …
18{{jsxref("Operators","后置递增","#Increment", 1)}}n/a… ++
{{jsxref("Operators","后置递减","#Decrement", 1)}}… --
17逻辑非 (!)从右到左! …
按位非 (~)~ …
一元加法 (+)+ …
一元减法 (-)- …
前置递增++ …
前置递减-- …
{{jsxref("Operators/typeof", "typeof")}}typeof …
{{jsxref("Operators/void", "void")}}void …
{{jsxref("Operators/delete", "delete")}}delete …
{{jsxref("Operators/await", "await")}}await …
16幂 (**)从右到左… ** …
15乘法 (*)从左到右… * …
除法 (/)… / …
取余 (%)… % …
14加法 (+)从左到右… + …
减法 (-)… - …
13按位左移 (<<)从左到右… << …
按位右移 (>>)… >> …
无符号右移 (>>>)… >>> …
12小于 (<)从左到右… < …
小于等于 (<=)… <= …
大于 (>)… > …
大于等于 (>=)… >= …
{{jsxref("Operators/in", "in")}}… in …
{{jsxref("Operators/instanceof", "instanceof")}}… instanceof …
11相等 (==)从左到右… == …
不相等 (!=)… != …
一致/严格相等 (===)… === …
不一致/严格不相等 (!==)… !== …
10按位与 (&)从左到右… & …
9按位异或 (^)从左到右… ^ …
8按位或 (|)从左到右… | …
7逻辑与 (&&)从左到右… && …
6逻辑或 (||)从左到右… || …
5空值合并 (??)从左到右… ?? …
4条件(三元)运算符从右到左… ? … : …
3赋值从右到左… = …
… += …
… -= …
… **= …
… *= …
… /= …
… %= …
… <<= …
… >>= …
… >>>= …
… &= …
… ^= …
… |= …
… &&= …
… ||= …
… ??= …
2{{jsxref("Operators/yield", "yield")}}从右到左yield …
{{jsxref("Operators/yield*", "yield*")}}yield* …
1逗号 / 序列从左到右… , …
\ No newline at end of file -- cgit v1.2.3-54-g00ecf