--- 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` は演算子に置き換わります。 ```js a OP1 b OP2 c ``` `OP1` と `OP2` の優先順位(下記の一覧表を参照)が異なる場合は、優先順位の高い演算子が先に実行され、結合性は関係ありません。コードの中で加算が先に書かれているにもかかわらず、乗算の方が加算よりも優先順位が高く、先に実行されていることを確認してください。 ```js console.log(3 + 10 * 2); // 23 を出力 console.log(3 + (10 * 2)); // 括弧の優先順位が高いので、23 を出力 console.log((3 + 10) * 2); // 括弧が順位を変更するので 26 を出力 ``` 左結合(左から右)は `(a OP1 b) OP2 c` のように処理されることであり、右結合(右から左)は `a OP1 (b OP2 c)` のように解釈されることです。代入演算子は右結合なので、このように書くことができます。 ```js 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)` と同じだからです。 ### グループ化と短絡評価の注意 下記の表では、**グループ化**が最上位の優先順位を持つものとして挙げられています。しかし、特に短絡が発生する場合は、グループ化記号 `( … )` の中の式が最初に評価されるとは限りません。 短絡評価は、条件付き評価を表す用語です。例えば、`a && (b + c)` という式において、`a` が{{Glossary("falsy", "偽値")}}である場合、従属式である `(b + c)` は括弧で囲まれていても評価されません。この論理的分離演算子 ("OR") は「短絡的」といえるでしょう。論理的分離演算子の他にも、ほかに短絡が発生する演算子には、論理的結合 ("AND") 演算子、Null 合体演算子、オプション連鎖演算子、条件演算子があります。以下に例を示します。 ```js 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` を出力 ``` ## 例 ```js 3 > 2 && 2 > 1 // true を返す 3 > 2 > 1 // 結果は false となる。3 > 2 は true であり、true は // 不等号で 1 に変換されるため、true > 1 は 1 > 1 となり、 // false となる。(3 > 2) > 1 のように括弧を付けると明確になる。 ``` ## 一覧表 以下の表は優先順位の最も高いもの (19) から最も低いもの (1) の順に並べられています。 なお、[スプレッド構文](/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax)はこの表から除外しています。 — 理由は [Stack Overflow の回答](https://stackoverflow.com/a/48656377)を引用します。「[スプレッド構文は演算子ではなく](https://stackoverflow.com/q/44934828/1048572)、優先度はありません。これは配列リテラルと関数呼び出し(およびオブジェクトリテラル)の構文の一部です。」
優先順位 演算子の種類 結合性 演算子
19 {{jsxref("Operators/Grouping", "グループ化", "", 1)}} なし ( … )
18 {{jsxref("Operators/Property_Accessors", "メンバーへのアクセス", "#Dot_notation", 1)}} 左から右 … . …
{{jsxref("Operators/Property_Accessors", "計算値によるメンバーへのアクセス","#Bracket_notation", 1)}} 左から右 … [ … ]
{{jsxref("Operators/new","new")}} (引数リスト付き) なし new … ( … )
関数呼び出し 左から右 … ( )
オプション連鎖 左から右 ?.
17 {{jsxref("Operators/new","new")}} (引数リストなし) 右から左 new …
16 {{jsxref("Operators","後置インクリメント","#インクリメントとデクリメント", 1)}} なし … ++
{{jsxref("Operators","後置デクリメント","#インクリメントとデクリメント", 1)}} … --
15 論理 NOT (!) 右から左 ! …
ビットごとの NOT (~) ~ …
単項 + + …
単項 - - …
前置インクリメント ++ …
前置デクリメント -- …
{{jsxref("Operators/typeof", "typeof")}} typeof …
{{jsxref("Operators/void", "void")}} void …
{{jsxref("Operators/delete", "delete")}} delete …
{{jsxref("Operators/await", "await")}} await …
14 べき乗 (**) 右から左 … ** …
13 乗算 (*) 左から右 … * …
除算 (/) … / …
剰余 (%) … % …
12 加算 (+) 左から右 … + …
減算(-) … - …
11 左ビットシフト (<<) 左から右 … << …
右ビットシフト … >> …
符号なし右ビットシフト (>>>) … >>> …
10 小なり (<) 左から右 … < …
小なりイコール (<=) … <= …
大なり (>) … > …
大なりイコール (>=) … >= …
{{jsxref("Operators/in", "in")}} … in …
{{jsxref("Operators/instanceof", "instanceof")}} … instanceof …
9 等価 (==) 左から右 … == …
不等価 (!=) … != …
厳密等価 (===) … === …
厳密不等価 (!==) … !== …
8 ビット単位 AND (&) 左から右 … & …
7 ビット単位 XOR (^) 左から右 … ^ …
6 ビット単位 OR (|) 左から右 … | …
5 論理 AND (&&) 左から右 … && …
4 論理 OR (||) 左から右 … || …
Null 合体 (??) 左から右 … ?? …
3 条件(三項)演算子 右から左 … ? … : …
2 代入 右から左 … = …
… += …
… -= …
… **= …
… *= …
… /= …
… %= …
… <<= …
… >>= …
… >>>= …
… &= …
… ^= …
… |= …
… &&= …
… ||= …
… ??= …
{{jsxref("Operators/yield", "yield")}} 右から左 yield …
{{jsxref("Operators/yield*", "yield*")}} yield* …
1 カンマ / シーケンス 左から右 … , …