1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
|
---
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 が設定されるのです。
他の例として、べき乗演算子だけが右結合性を持ちますが、他の算術演算子は左結合性を持ちます。興味深いのは、結合性や優先順位に関係なく、評価の順序は常に左から右になることです。
<table class="standard-table">
<tbody>
<tr>
<td>コード</td>
<td>出力結果</td>
</tr>
<tr>
<td>
<pre class="brush: js">
function echo(name, num) {
console.log("Evaluating the " + name + " side");
return num;
}
// 除算演算子 (/) の場合
console.log(echo("left", 6) / echo("right", 2));
</pre>
</td>
<td>
<pre class="brush: plain">
Evaluating the left side
Evaluating the right side
3
</pre>
</td>
</tr>
<tr>
<td>
<pre class="brush: js">
function echo(name, num) {
console.log("Evaluating the " + name + " side");
return num;
}
// べき乗演算子 (**) の場合
console.log(echo("left", 2) ** echo("right", 3));
</pre>
</td>
<td>
<pre class="brush: plain">
Evaluating the left side
Evaluating the right side
8</pre>
</td>
</tr>
</tbody>
</table>
結合性の違いは、同じ優先順位の演算子が複数存在する場合に現れます。上の例のように演算子が一つだけの場合や、演算子の優先順位が異なる場合は、結合性は出力に影響を与えません。下の例では、同じ演算子が複数使われている場合に、結合性が出力結果にどのような影響を与えるかを見てみましょう。
<table class="standard-table">
<tbody>
<tr>
<td>コード</td>
<td>出力結果</td>
</tr>
<tr>
<td>
<pre class="brush: js">
function echo(name, num) {
console.log("Evaluating the " + name + " side");
return num;
}
// 除算演算子 (/) の場合
console.log(echo("left", 6) / echo("middle", 2) / echo("right", 3));
</pre>
</td>
<td>
<pre class="brush: plain">
Evaluating the left side
Evaluating the middle side
Evaluating the right side
1
</pre>
</td>
</tr>
<tr>
<td>
<pre class="brush: js">
function echo(name, num) {
console.log("Evaluating the " + name + " side");
return num;
}
// べき乗演算子 (**) の場合
console.log(echo("left", 2) ** echo("middle", 3) ** echo("right", 2));
</pre>
</td>
<td>
<pre class="brush: plain">
Evaluating the left side
Evaluating the middle side
Evaluating the right side
512
</pre>
</td>
</tr>
<tr>
<td>
<pre class="brush: js">
function echo(name, num) {
console.log("Evaluating the " + name + " side");
return num;
}
// 左と中央の間のべき乗を括弧で囲んだ場合
console.log((echo("left", 2) ** echo("middle", 3)) ** echo("right", 2));</pre>
</td>
<td>
<pre class="brush: plain">
Evaluating the left side
Evaluating the middle side
Evaluating the right side
64</pre
>
</td>
</tr>
</tbody>
</table>
上記のコードを見てください。`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)、優先度はありません。これは配列リテラルと関数呼び出し(およびオブジェクトリテラル)の構文の一部です。」
<table class="fullwidth-table">
<tbody>
<tr>
<th>優先順位</th>
<th>演算子の種類</th>
<th>結合性</th>
<th>演算子</th>
</tr>
<tr>
<td>19</td>
<td>
{{jsxref("Operators/Grouping", "グループ化", "", 1)}}
</td>
<td>なし</td>
<td><code>( … )</code></td>
</tr>
<tr>
<td rowspan="5">18</td>
<td>
{{jsxref("Operators/Property_Accessors", "メンバーへのアクセス", "#Dot_notation", 1)}}
</td>
<td>左から右</td>
<td><code>… . …</code></td>
</tr>
<tr>
<td>
{{jsxref("Operators/Property_Accessors", "計算値によるメンバーへのアクセス","#Bracket_notation", 1)}}
</td>
<td>左から右</td>
<td><code>… [ … ]</code></td>
</tr>
<tr>
<td>{{jsxref("Operators/new","new")}} (引数リスト付き)</td>
<td>なし</td>
<td><code>new … ( … )</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Guide/Functions">関数呼び出し</a>
</td>
<td>左から右</td>
<td>
<code>… ( <var>… </var>)</code>
</td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining">オプション連鎖</a>
</td>
<td>左から右</td>
<td><code>?.</code></td>
</tr>
<tr>
<td>17</td>
<td>
{{jsxref("Operators/new","new")}} (引数リストなし)
</td>
<td>右から左</td>
<td><code>new …</code></td>
</tr>
<tr>
<td rowspan="2">16</td>
<td>
{{jsxref("Operators","後置インクリメント","#インクリメントとデクリメント", 1)}}
</td>
<td rowspan="2">なし</td>
<td><code>… ++</code></td>
</tr>
<tr>
<td>{{jsxref("Operators","後置デクリメント","#インクリメントとデクリメント", 1)}}</td>
<td><code>… --</code></td>
</tr>
<tr>
<td rowspan="10">15</td>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Logical_NOT">論理 NOT (!)</a>
</td>
<td rowspan="10">右から左</td>
<td><code>! …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Bitwise_NOT">ビットごとの NOT (~)</a>
</td>
<td><code>~ …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Unary_plus">単項 +</a>
</td>
<td><code>+ …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Unary_negation">単項 -</a>
</td>
<td><code>- …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators#インクリメントとデクリメント">前置インクリメント</a>
</td>
<td><code>++ …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators#インクリメントとデクリメント">前置デクリメント</a>
</td>
<td><code>-- …</code></td>
</tr>
<tr>
<td>{{jsxref("Operators/typeof", "typeof")}}</td>
<td><code>typeof …</code></td>
</tr>
<tr>
<td>{{jsxref("Operators/void", "void")}}</td>
<td><code>void …</code></td>
</tr>
<tr>
<td>{{jsxref("Operators/delete", "delete")}}</td>
<td><code>delete …</code></td>
</tr>
<tr>
<td>{{jsxref("Operators/await", "await")}}</td>
<td><code>await …</code></td>
</tr>
<tr>
<td>14</td>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Exponentiation">べき乗 (**)</a>
</td>
<td>右から左</td>
<td><code>… ** …</code></td>
</tr>
<tr>
<td rowspan="3">13</td>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Multiplication">乗算 (*)</a>
</td>
<td rowspan="3">左から右</td>
<td><code>… * …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Division">除算 (/)</a>
</td>
<td><code>… / …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Remainder">剰余 (%)</a>
</td>
<td><code>… % …</code></td>
</tr>
<tr>
<td rowspan="2">12</td>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Addition">加算 (+)</a>
</td>
<td rowspan="2">左から右</td>
<td><code>… + …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Subtraction">減算(-)</a>
</td>
<td><code>… - …</code></td>
</tr>
<tr>
<td rowspan="3">11</td>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Left_shift">左ビットシフト (<<)</a>
</td>
<td rowspan="3">左から右</td>
<td><code>… << …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Right_shift">右ビットシフト</a>
</td>
<td><code>… >> …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Unsigned_right_shift">符号なし右ビットシフト (>>>)</a>
</td>
<td><code>… >>> …</code></td>
</tr>
<tr>
<td rowspan="6">10</td>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Less_than">小なり (<)</a>
</td>
<td rowspan="6">左から右</td>
<td><code>… < …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Less_than_or_equal">小なりイコール (<=)</a>
</td>
<td><code>… <= …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Greater_than">大なり (>)</a>
</td>
<td><code>… > …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Greater_than_or_equal">大なりイコール (>=)</a>
</td>
<td><code>… >= …</code></td>
</tr>
<tr>
<td>{{jsxref("Operators/in", "in")}}</td>
<td><code>… in …</code></td>
</tr>
<tr>
<td>{{jsxref("Operators/instanceof", "instanceof")}}</td>
<td><code>… instanceof …</code></td>
</tr>
<tr>
<td rowspan="4">9</td>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Equality">等価 (==)</a>
</td>
<td rowspan="4">左から右</td>
<td><code>… == …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Inequality">不等価 (!=)</a>
</td>
<td><code>… != …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Strict_equality">厳密等価 (===)</a>
</td>
<td><code>… === …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Strict_inequality">厳密不等価 (!==)</a>
</td>
<td><code>… !== …</code></td>
</tr>
<tr>
<td>8</td>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Bitwise_AND">ビット単位 AND (&)</a>
</td>
<td>左から右</td>
<td><code>… & …</code></td>
</tr>
<tr>
<td>7</td>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Bitwise_XOR">ビット単位 XOR (^)</a>
</td>
<td>左から右</td>
<td><code>… ^ …</code></td>
</tr>
<tr>
<td>6</td>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Bitwise_OR">ビット単位 OR (|)</a>
</td>
<td>左から右</td>
<td><code>… | …</code></td>
</tr>
<tr>
<td>5</td>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Logical_AND">論理 AND (&&)</a>
</td>
<td>左から右</td>
<td><code>… && …</code></td>
</tr>
<tr>
<td rowspan="2">4</td>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Logical_OR">論理 OR (||)</a>
</td>
<td>左から右</td>
<td><code>… || …</code></td>
</tr>
<tr>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator">Null 合体 (??)</a>
</td>
<td>左から右</td>
<td><code>… ?? …</code></td>
</tr>
<tr>
<td>3</td>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">条件(三項)演算子</a>
</td>
<td>右から左</td>
<td><code>… ? … : …</code></td>
</tr>
<tr>
<td rowspan="18">2</td>
<td rowspan="16">
<a href="/ja/docs/Web/JavaScript/Reference/Operators#assignment_operators">代入</a>
</td>
<td rowspan="16">右から左</td>
<td><code>… = …</code></td>
</tr>
<tr>
<td><code>… += …</code></td>
</tr>
<tr>
<td><code>… -= …</code></td>
</tr>
<tr>
<td><code>… **= …</code></td>
</tr>
<tr>
<td><code>… *= …</code></td>
</tr>
<tr>
<td><code>… /= …</code></td>
</tr>
<tr>
<td><code>… %= …</code></td>
</tr>
<tr>
<td><code>… <<= …</code></td>
</tr>
<tr>
<td><code>… >>= …</code></td>
</tr>
<tr>
<td><code>… >>>= …</code></td>
</tr>
<tr>
<td><code>… &= …</code></td>
</tr>
<tr>
<td><code>… ^= …</code></td>
</tr>
<tr>
<td><code>… |= …</code></td>
</tr>
<tr>
<td><code>… &&= …</code></td>
</tr>
<tr>
<td><code>… ||= …</code></td>
</tr>
<tr>
<td><code>… ??= …</code></td>
</tr>
<tr>
<td>{{jsxref("Operators/yield", "yield")}}</td>
<td rowspan="2">右から左</td>
<td><code>yield …</code></td>
</tr>
<tr>
<td>{{jsxref("Operators/yield*", "yield*")}}</td>
<td><code>yield* …</code></td>
</tr>
<tr>
<td>1</td>
<td>
<a href="/ja/docs/Web/JavaScript/Reference/Operators/Comma_Operator">カンマ / シーケンス</a>
</td>
<td>左から右</td>
<td><code>… , …</code></td>
</tr>
</tbody>
</table>
|