Get to know MDN better
このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。
演算子の優先順位は、演算子が互いにどのように解釈されるかを決定します。優先度の高い演算子は、優先度の低い演算子のオペランドになります。
以下の表現で記述できる式を考えてみましょう。なお、OP1 と OP2 は演算子に置き換わります。
a OP1 b OP2 c上記の組み合わせには 2 つの解釈の可能性があります。
(a OP1 b) OP2 c a OP1 (b OP2 c)言語がどちらを採用するかは、OP1とOP2の組み合わせによって決まります。
OP1 と OP2 の優先順位(下記の一覧表を参照)が異なる場合は、優先順位の高い演算子が先に実行され、結合性は関係ありません。コードの中で加算が先に書かれているにもかかわらず、乗算の方が加算よりも優先順位が高く、先に実行されていることを確認してください。
同じ優先度の演算子同士では、言語は「結合性」によってグループ化します。左結合(左→右)は (a OP1 b) OP2 c のように処理されることであり、右結合(右→左)は a OP1 (b OP2 c) のように解釈されることです。代入演算子は右結合なので、このように書くことができます。
これで、a と b が 5 の値を得るという期待通りの結果を得ることができます。これは代入演算子が代入した値を返すためです。まず b に 5 が設定されます。そして a にも、代入演算子の右オペランドである b = 5 が返す 5 が設定されるのです。
他の例として、べき乗演算子だけが右結合性を持ちますが、他の算術演算子は左結合性を持ちます。
演算子は最初のステップで優先順位によってグループ化され、次に同じ優先順位を持つ隣接する演算子については関連付けられた結合性によってグループ化されます。したがって、除算と累乗が混在している場合、累乗演算は常に除算より先に実行されます。例えば、2 ** 3 / 3 ** 2 は (2 ** 3) / (3 ** 2) と同等であるため、結果は 0.8888888888888888 となります。
前置単項演算子の場合、次のパターンを考えてみてください。
OP1 a OP2 bここで、OP1 は前置単項演算子であり、OP2 は二項演算子です。 OP1 の優先順位が OP2 より高い場合、(OP1 a) OP2 b としてグループ化されます。そうでない場合は、OP1 (a OP2 b) となります。
単項演算子が 2 つ目オペランドである場合、
a OP2 OP1 b二項演算子 OP2 が a OP2 (OP1 b) のようにグループ化されるためには、単項演算子 OP1 よりも優先順位が低くないといけません。例えば、次のものは無効です。
+ 演算子は yield よりも優先順位が高いため、これは (a + yield) 1 となります。しかし、 yield はジェネレーター関数における予約語であるため、これは構文エラーとなります。幸いなことに、ほとんどの単項演算子は二項演算子よりも優先順位が高く、この落とし穴に悩まさずに済みます。
2 つの前置単項演算子が指定された場合はどうでしょうか。
OP1 OP2 aオペランドにより近い単項演算子 OP2 は、OP1 (OP2 a) としてグループ化されるためには、優先順位が OP1 より高くなければなりません。 それ以外の方法により、(OP1 OP2) a となる可能性があります。
await は yield よりも優先順位が高いため、これは (await yield) 1 となり、yield という名前の識別子を待機することになり、構文エラーとなります。同様に、new !A; と記述した場合、! の優先順位が new より低いため、これは (new !) A となり、明らかに不正な構文となります。(!A は常に論理値を生成し、コンストラクター関数ではないので、これはそもそも意味をなさないように見えます。)
後置単項演算子(すなわち ++ と --)についても同様の規則が適用されます。幸いなことに、どちらの演算子も二項演算子よりも優先順位が高いため、括弧の付け方は常に期待通りになります。さらに、 ++ は参照ではなく値を評価するため、複数のインクリメントを連結することもできません。
演算子の優先順位は再帰的に処理されます。例えば、次の式を考えてみましょう。
まず、異なる優先度を持つ演算子を優先度の高い順にグループ化します。
*// グループ内では、両方が左結合であるため、左オペランドがグループ化されます。
演算子の優先順位と結合性は、演算子の評価順序(暗黙のグループ化)にのみ影響し、オペランドの評価順序には影響しないことに注意してください。オペランドは常に左→右へ評価されます。優先順位の高い式は常にまず評価され、その結果は演算子の優先順序に従って組み合わされます。
二分木に慣れている場合は、これを後順走査と考えてください。
/ ┌────────┴────────┐ echo("左", 4) ** ┌────────┴────────┐ echo("中", 3) echo("右", 2)すべての演算子が適切にグループ化された後、二項演算子は二分木を形成します。評価は最も外側のグループ(これは優先度が最も低い演算子 /)から始まります。この演算子の左オペランドがまず評価され、そこにはより優先度の高い演算子(呼び出し式 echo("left", 4) など)が含まれる可能性があります。左オペランドの評価後、右オペランドも同様の方法で評価されます。したがって、結合する演算子の優先度に関係なく、すべての葉ノード(echo() 呼び出し)は左→右へ走査されます。
前節では「優先順位の高い式は常に先に評価する」と言いましたが、これは一般的に正しいものの、「短絡評価」の存在を考慮する必要があります。短絡評価の場合、オペランドがまったく評価されない可能性があります。
短絡評価は、条件付き評価を表す用語です。例えば、a && (b + c) という式において、a が偽値である場合、従属式である (b + c) は括弧で囲まれていて && より優先順位が高くても評価されません。この論理積演算子 (&&) は「短絡的」といえるでしょう。論理積演算子に加えて、その他の短絡評価される演算子には、論理和演算子 (||)、ヌル値合体演算子 (??)、オプショナルチェーン演算子 (?.) があります。
短絡評価される演算子を評価する際、左オペランドは常に評価されます。右オペランドは、左オペランドで操作の結果を決定できない場合にのみ評価されます。
メモ: 短絡評価の挙動は、これらの演算子に組み込まれています。 その他の演算子は、実際に有用かどうかに関わらず、常に両方のオペランドを評価します。 例えば、NaN * foo() は、結果が NaN 以外の値になることが絶対にない場合でも、常に foo を呼び出します。
前述の後順走査のモデルはこの場合も有効です。ただし、短絡評価演算子の左部分木を走査した後、言語は右オペランドの評価が必要かどうかを判断します。必要がない場合(例えば || の左オペランドが既に真値である場合など)、右部分木を走査せずに結果が直接返されます。
この場合を考えてみてください。
&&の優先順位がより高いにもかかわらず、C()のみが評価されます。これは||の優先順位がより高いということではありません——まさに(B() && A())の優先順位がより高いために、全体として無視されるのです。次のように再配置すると、
&& の短絡評価の効果で B() の評価を阻止しますが、A() && B() 全体が false であるため、C() は評価されます。
ただし、短絡評価しても最終的な評価結果は変わりません。短絡評価はオペランドの評価にのみ影響し、演算子のグループ化方法には影響しません。オペランドの評価が副作用を持たない(例えば、コンソールへの出力、変数への割り当てる、エラーが発生する)場合、短絡評価はまったく認識できません。
これらの演算子の代入形(&&=、 ||=、??=)も同様に短絡評価が行われます。これらの演算子では、短絡評価が行われると、代入がまったく現れなくなります。
以下の表は優先順位の最も高いもの (18) から最も低いもの (1) の順に並べられています。
この表に関する全般的な注意:
| 18: グループ化 | なし | グループ化 (x) |
[1] |
| 17: アクセスと呼び出し | 左→右 | メンバーアクセス x.y |
[2] |
| オプショナルチェーン x?.y |
|||
| なし |
計算値によるメンバーアクセス x[y] |
[3] | |
| 引数リスト付きの new new x(y) |
[4] | ||
|
関数呼び出し x(y) |
|||
| import(x) | |||
| 16: new | なし | 引数リストなしの new new x |
|
| 15: 後置演算子 | なし |
後置インクリメント x++ |
[5] |
|
後置デクリメント x-- |
|||
| 14: 前置演算子 | なし |
前置インクリメント ++x |
[6] |
|
前置デクリメント --x |
|||
|
論理否定 !x |
|||
|
ビット否定 ~x |
|||
|
単項プラス +x |
|||
|
単項マイナス -x |
|||
| typeof x | |||
| void x | |||
| delete x | [7] | ||
| await x | |||
| 13: べき乗 | 右→左 |
べき乗 x ** y |
[8] |
| 12: 乗法的演算子 | 左→右 |
乗算 x * y |
|
|
除算 x / y |
|||
|
剰余 x % y |
|||
| 11: 加算的演算子 | 左→右 |
加算 x + y |
|
|
減算 x - y |
|||
| 10: ビットシフト | 左→右 |
左シフト x << y |
|
|
右シフト x >> y |
|||
|
符号なし右シフト x >>> y |
|||
| 9: 関係演算子 | 左→右 |
小なり x < y |
|
|
小なりイコール x <= y |
|||
|
大なり x > y |
|||
|
大なりイコール x >= y |
|||
| x in y | |||
| x instanceof y | |||
| 8: 等価性演算子 | 左→右 |
等価 x == y |
|
|
不等価 x != y |
|||
|
厳密等価 x === y |
|||
|
厳密不等価 x !== y |
|||
| 7: ビット論理積 | 左→右 |
ビット論理積 x & y |
|
| 6: ビット排他的論理和 | 左→右 |
ビット排他的論理和 x ^ y |
|
| 5: ビット論理和 | 左→右 |
ビット論理和 x | y |
|
| 4: 論理積 | 左→右 |
論理積 x && y |
|
| 3: 論理和、ヌル値合体 | 左→右 |
論理和 x || y |
|
|
ヌル値合体 x ?? y |
[9] | ||
| 2: 代入とその他 | 右→左 |
代入 x = y |
[10] |
|
加算代入 x += y |
|||
|
減算代入 x -= y |
|||
|
べき乗代入 x **= y |
|||
|
乗算代入 x *= y |
|||
|
除算代入 x /= y |
|||
|
剰余代入 x %= y |
|||
|
左シフト代入 x <<= y |
|||
|
右シフト代入 x >>= y |
|||
|
符号なし右シフト代入 x >>>= y |
|||
|
ビット論理積代入 x &= y |
|||
|
ビット排他的論理和代入 x ^= y |
|||
|
ビット論理和代入 x |= y |
|||
|
論理積代入 x &&= y |
|||
|
論理和代入 x ||= y |
|||
|
ヌル値合体代入 x ??= y |
|||
| 右→左 |
条件(三項)演算子 x ? y : z |
[11] | |
| 右→左 |
アロー x => y |
[12] | |
| なし | yield x | ||
| yield* x | |||
|
スプレッド ...x |
[13] | ||
| 1: カンマ | 左→右 |
カンマ演算子 x, y |
注釈:
グループ 17 と 16 の優先順位はやや曖昧かもしれません。明確にするために、いくつか例を挙げます。
This page was last modified on 2026年4月1日 by MDN contributors.
Your blueprint for a better internet.
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998–2026 by individual mozilla.org contributors. Content available under a Creative Commons license.