AI生成コンテンツ / AI-generated content
演算の優先順位
これまで紹介してきた演算子の優先順位には、算数・数学で習った規則と共通するものも多い。ここで、主な優先順位を一覧にしておこう。
取り上げるプログラムは、これまでダウンロードしたものである。
| 順位 | 演算子 | 演算 |
|---|---|---|
| 18 | (...) | グループ化 |
| 17 | … . … | メンバへのアクセス |
| … [ … ] | 計算値によるメンバへのアクセス | |
| new … ( … ) | new (引数リスト付き) | |
| … ( … ) | 関数呼び出し | |
| ?. | オプショナルチェーン | |
| 16 | new … | new (引数リストなし) |
| 15 | ... ++ | 後置インクリメント |
| ... -- | 後置デクリメント | |
| 14 | ! ... | 論理否定 |
| ~ ... | ビット否定 | |
| + ... | 単項 + | |
| - ... | 単項 - | |
| ++ ... | 前置インクリメント | |
| -- ... | 前置デクリメント | |
| typeof ... | typeof | |
| void ... | void | |
| delete ... | delete | |
| await | await | |
| 13 | ** | べき乗 |
| 12 | * | 乗算 |
| / | 除算 | |
| % | 剰余算 | |
| 11 | + | 加算 |
| - | 減算 | |
| 10 | << | 左ビットシフト |
| >> | 右ビットシフト | |
| >>> | 符号無し右ビットシフト | |
| 9 | < | 小なり |
| <= | 以下 | |
| > | 大なり | |
| >= | 以上 | |
| in | in | |
| instanceof | instanceof | |
| 8 | == | 等価 |
| != | 不等価 | |
| === | 厳密等価 | |
| !== | 厳密不等価 | |
| 7 | & | ビット論理積 |
| 6 | ^ | ビット排他的論理和 |
| 5 | | | ビット論理和 |
| 4 | && | 論理積 |
| 3 | || | 論理和 |
| ?? | Null合体 | |
| 2 | ... ? ... : ... | 条件(三項)演算 |
| 2 | = += -= **= *= /= %= <<= >>= >>>= &= ^= |= &&= ||= ??= | 代入演算 |
| yield | yield | |
| yield* | yield* | |
| 1 | , | カンマ |
div1.html
10: let a = 1, b = 2;
11: let c = a / b;
comp4.html
26: if ((year >= 1980) && (year <= 1989)) {
27: result = 'です';
28: } else {
セミコロン ; は文の区切りに使う。JavaScriptには、一定の条件でセミコロンを補う自動セミコロン挿入(ASI)があるが、改行した場所で必ず文が終わるわけではない。意図しない解釈を避けるため、本編では文末にセミコロンを書く。
コメント
increment1.html
20: //ページのロード時に実行
21: window.onload = function() {
logic1.html
22: const a = true;
23: const b = false;
bit1.html
19: <script>
20: /**
21: * 計算と画面表示
22: */
23: function execute() {
コラム:オペランドと結合性
たとえば $$ 1 + 2 $$ では、演算子は $ + $(加算)で、オペランドは $ 1 $ と $ 2 $ である。
$$ 2 * x $$ では、演算子は $ * $(乗算)で、オペランドは $ 2 $ と $ x $ である。
次に、優先順位が同じ演算子をどのようにまとめるかを見ておこう。$$ 1 + 2 + 4 $$ の加算演算子 $ + $ は左結合なので、$$ (1 + 2) + 4 $$ とまとめられ、結果は $ 7 $ になる。このまとめ方を結合性という。
ただし、結合性はオペランドそのものを読み出す順序とは異なる。また、論理積 && や論理和 |
| 順位 | 演算子 | 演算 | 結合性 |
|---|---|---|---|
| 18 | (...) | グループ化 | なし |
| 17 | … . … | メンバへのアクセス | 左から右 |
| … [ … ] | 計算値によるメンバへのアクセス | 左から右 | |
| new … ( … ) | new (引数リスト付き) | なし | |
| … ( … ) | 関数呼び出し | 左から右 | |
| ?. | オプショナルチェーン | ||
| 16 | new … | new (引数リストなし) | なし |
| 15 | ... ++ | 後置インクリメント | なし |
| ... -- | 後置デクリメント | なし | |
| 14 | ! ... | 論理否定 | 右から左 |
| ~ ... | ビット否定 | ||
| + ... | 単項 + | ||
| - ... | 単項 - | ||
| ++ ... | 前置インクリメント | ||
| -- ... | 前置デクリメント | ||
| typeof ... | typeof | ||
| void ... | void | ||
| delete ... | delete | ||
| await | await | ||
| 13 | ** | べき乗 | 右から左 |
| 12 | * | 乗算 | 左から右 |
| / | 除算 | ||
| % | 剰余算 | ||
| 11 | + | 加算 | 左から右 |
| - | 減算 | ||
| 10 | << | 左ビットシフト | 左から右 |
| >> | 右ビットシフト | ||
| >>> | 符号無し右ビットシフト | ||
| 9 | < | 小なり | 左から右 |
| <= | 以下 | ||
| > | 大なり | ||
| >= | 以上 | ||
| in | in | ||
| instanceof | instanceof | ||
| 8 | == | 等価 | 左から右 |
| != | 不等価 | ||
| === | 厳密等価 | ||
| !== | 厳密不等価 | ||
| 7 | & | ビット論理積 | 左から右 |
| 6 | ^ | ビット排他的論理和 | 左から右 |
| 5 | | | ビット論理和 | 左から右 |
| 4 | && | 論理積 | 左から右 |
| 3 | || | 論理和 | 左から右 |
| ?? | Null合体 | 左から右 | |
| 2 | ... ? ... : ... | 条件(三項)演算 | 右から左 |
| 2 | = += -= **= *= /= %= <<= >>= >>>= &= ^= |= &&= ||= ??= | 代入演算 | 右から左 |
| yield | yield | 右から左 | |
| yield* | yield* | 右から左 | |
| 1 | , | カンマ | 左から右 |
代入演算子 $ = $ は、右辺の値を左辺へ代入し、代入した値を式全体の値として返す。したがって、$$ x = 1 + 2 + 4 $$ では $ 7 $ が $ x $ に代入される。また、$$ y = x = 1 + 2 + 4 $$ は右から $$ y = (x = 7) $$ とまとめられ、$ x $ と $ y $ の両方に $ 7 $ が代入される。
練習問題:演算の優先順位
コラム:strict mode
ところが、大規模なシステム開発を行うのに、旧来の言語仕様に好ましくないものが幾つも出てきた。そこで、2009年(平成21年)12月に公開された ES5 では、strict mode というモードを設け、好ましくない仕様で書いたプログラムは実行時にエラーを出すようにした。
たとえば、"strict1.html" を実行してみてほしい。
strict1.html
20: <script>
21: //ページのロード時に実行
22: window.onload = function() {
23: a = 1;
24: document.getElementById('let1').textContent = a.toString();
25: }
26: </script>
しかし、大規模なシステム開発において安易にグローバル変数が宣言できてしまうのは好ましくない。
JavaScriptの冒頭に "use strict"; と1行記述すると、そのスクリプトは strict mode になる。関数の本体の冒頭に書けば、その関数だけに適用できる。
"strict2.html" を実行してみてほしい。画面には何も表示しなくなるが、コンソールを見るとエラーが出ているのが分かる。
strict2.html
20: <script>
21: "use strict"; // strict mode
22:
23: //ページのロード時に実行
24: window.onload = function() {
25: a = 1; // エラーになる
26: document.getElementById('let1').textContent = a.toString();
27: }
28: </script>
■書き換え不可なプロパティへの代入
"use strict";■getter しかないプロパティへの代入
var obj = {};
Object.defineProperty(obj, "x", { value: 1, writable: false });
obj.x = 2; // ❌ TypeError: Cannot assign to read only property 'x'
"use strict";■delete の禁止対象を削除
var obj = {
get x() { return 10; }
};
obj.x = 20; // ❌ TypeError
"use strict";■ 重複する引数名
delete Object.prototype; // ❌ TypeError
"use strict";■ 8進数リテラル
function f(x, x) { // ❌ SyntaxError
return x;
}
"use strict";■ with 文の禁止
var x = 010; // ❌ SyntaxError (先頭0の数値リテラル禁止)
"use strict";■ 関数内のthisが自動でグローバルオブジェクトを指さなくなる
var obj = {a: 1};
with (obj) { // ❌ SyntaxError
console.log(a);
}
"use strict";本編では、できる限り strict mode でも問題なく動くプログラムを紹介しているが、サンプルを短くするため "use strict"; は明示していない。
function f() {
console.log(this); // undefined(通常のブラウザースクリプトではwindow)
}
f();
なお、JavaScriptモジュール(ESモジュール)は、指定しなくても常に strict mode で実行される。
コラム:アセンブラ、コンパイラ、インタプリタ
現代のJavaScriptエンジンは、インタプリタだけで動くとは限らない。たとえばV8は、ソースコードをバイトコードへ変換して実行し、繰り返し使われる部分をJIT(実行時)コンパイラで最適化された機械語へ変換する。JavaScriptという言語の仕様と、処理系が採用する実行方式は分けて考える必要がある。
参考サイト
- 演算子の優先順位:MDN Web Docs
- コメント:MDN Web Docs
- 厳格モード:MDN Web Docs
- Launching Ignition and TurboFan:V8
