[JavaScript講座] 構文ルールと “use strict”

当ページのリンクには広告が含まれています。
目次

文(statement)と式(expression)

「式」は値になるもの

式(expression) は、「評価すると値になるもの」と理解してOKです。

式の例:

1 + 2           // 3 という値になる
"Hello"         // "Hello" という値そのもの
a * 5           // a の値によって別の値になる
true && false   // false になる

これらはすべて「式」です。
式は 「値として扱える」 のがポイントです。

const x = 1 + 2;          // 右辺は式
console.log(1 + 2 * 3);   // 引数の中も式
someFunc(a + b, c * d);   // 引数に式を渡している

「文」は命令

文(statement) は「何かをしなさい」という命令だと思ってください。

文の例:

let x = 10;        // 変数宣言文
x = x + 1;         // 代入文
if (x > 10) { ... } // if文
for (let i = 0; i < 10; i++) { ... } // for文
return x;          // return文
  • プログラムは「文」の並びで構成される
  • 文の中で、条件や右辺などに「式」が使われる

式文(expression statement)

JavaScript では、「式だけ書いた1行」も文として扱われる ことが多いです。

1 + 2;            // 式文(結果はどこにも使われない)
console.log("A"); // これは「式」でもあり、「文」でもある
  • 「文の中に式がある」
  • でも「式単体も文として書ける」

という関係がある、と覚えておけばOKです。

実務でも「式と文の違い」が効いてくるのは、

  • アロー関数の「式ボディ」「ブロックボディ」
  • 条件演算子 cond ? a : b

などを扱うときです。
今は 「値になるかどうか」 だけ意識しておけば十分です。

ブロック {} とスコープのイメージ

ブロック(block) とは、単に { ... } で囲まれた文の集まりです。

{
  console.log("ここはブロックの中");
  const x = 10;
  console.log(x);
}
  • ブロック自体は値ではありません(式ではない)
  • ブロックの中に複数の文を書いて、ひとかたまりにするイメージ

iffor でも必ずブロックが出てきます。

if (condition) {
  // ここがブロック
  console.log("trueのときだけ実行");
  const x = 1;
}

ブロックは、以下の2つの意味があります。

  • 「見た目を整理するため」
  • let / const のスコープを区切るため」

スコープの話は後の章で深掘りしますが、今の段階では、

「{} で囲むと、その中だけで有効な変数を作れる」

くらいのイメージでOKです。

セミコロンと自動セミコロン挿入(ASI)

セミコロンの役割

JavaScriptでは、基本的に 1つの文の終わりにセミコロン ; を付けます。

const x = 10;
const y = 20;
console.log(x + y);

ただし、iffor のような文は構造自体に区切りがあるので、
その後ろにセミコロンはつけません。

if (x > 10) {
  console.log("大きい");
}  // ここには ; は不要

ASI(Automatic Semicolon Insertion)

JavaScriptエンジンは、「ある程度」は勝手にセミコロンを補ってくれる仕様になっています。
これが ASI(Automatic Semicolon Insertion)です。

良くも悪くも「そこそこ賢い」ので、次のような書き方も動きます。

const x = 10
const y = 20
console.log(x + y)

エンジンは内部的に以下のように解釈します。

const x = 10;
const y = 20;
console.log(x + y);

ASIの危険な例(return の罠)

ASI には危険なパターンがあります。代表例が return

function getValue() {
  return
    1;
}

ぱっと見、「1を返しているように」見えますが、実際には、

function getValue() {
  return;   // ここでセミコロンが挿入されてしまう
    1;
}

と解釈され、undefined を返す関数になってしまいます。

return の後ろを改行したいときは必ずこう書きます。

function getValue() {
  return 1; // 同じ行に値を書く
}

他にもあるASlのクセ

他にも、演算子と改行の組み合わせでバグりやすいパターンがあります。

let a = 1;
let b = 2;

a
++
b;

これは見た目は a++b; に見えますが、
実際には a; ++b; と解釈されるなど、ややこしい挙動になります。

実務的な指針

  • 初心者〜中級くらいまでは、素直に「文の末尾にセミコロンを書く」方針が安全です。
  • ASI をフルに信用して「ノーセミコロン派」でいく場合は、
    • Linter(ESLint)を必ず入れる
    • チーム全体でスタイルを統一することがほぼ必須になります。

この講座では、基本的にセミコロンを書くスタイルで進めます。

“use strict” とは何か

strict mode のイメージ

"use strict"; は、JavaScriptに 「厳密モードで実行して」 と指示するための文です。

"use strict";

x = 10; // エラー(宣言していない変数への代入)

strict mode では、従来の「ゆるい挙動」の一部がエラーになり、バグを早期に発見しやすくなります。

どうやって有効になる?

strict mode の有効化には 2 パターンあります。

ファイル全体(スクリプト全体)に適用

ファイルの先頭に "use strict"; を書くと、そのファイル全体が strict になります。

"use strict";

function func() {
  // このファイルのコードは全部 strict mode
}

関数の中だけ適用

関数の先頭に"use strict"; を書くと、その関数だけが strict になります。

function func() {
  "use strict"; // この関数の中だけ strict
  // ...
}

この書き方は、レガシーコードの一部だけ strict にする時などに使います。

なお、ES Modules(import / export を使うモジュール)は常に strict mode です。
以降の章で詳しく触れますが、「モジュールなら自動的に厳密モードになる」と覚えてOKです。

strict mode で何が変わるか(代表例)

厳密に挙げるとかなりの数がありますが、実務で効いてくるのは主に以下です。

暗黙のグローバルが禁止される

非 strict:

function func() {
  x = 10; // 宣言なし代入 → 暗黙のグローバル変数になってしまう
}
func();
console.log(x);

strict:

"use strict";

function func() {
  x = 10; // ReferenceError: x is not defined
}
func();

宣言なしの代入が即エラーになるので、タイポやミスにすぐ気付けます。

this の挙動が変わる(関数内)

非 strict:

function showThis() {
  console.log(this); // ブラウザなら window、Node なら global
}
showThis();

strict:

"use strict";

function showThis() {
  console.log(this); // undefined
}
showThis();

strict では「ただの関数呼び出し」の thisundefined になります。
この方が、「this は明示的に指定しないといけない」という意識が強くなるので、バグを減らせます。

this の詳細は後の章で解説します)

重複したパラメータ名が使えない

非 strict では、以下も一応動きます(動くが、かなり危険):

function f(a, a) {
  console.log(a);
}

strict ではこれは構文エラーになります。

"use strict";

function f(a, a) {} // SyntaxError

一部の危険な構文が禁止

例:

  • with 文が禁止
  • 8進数リテラルの一部の書き方が非推奨〜禁止

結論:基本的に strict mode 前提で考える

モダンなコードでは、

  • モジュールは自動 strict
  • スクリプトも "use strict" を書くか、bundler で ES Modules 化されることが多い

なので、この講座でも「strict で動かす前提」で解説します。

スクリプトとモジュールの違い(概要)

スクリプト(従来の <script>

<script src="main.js"></script>
  • 非 strict でも動く("use strict" を書かなければゆるいモード)
  • top-level の this
  • ブラウザ → window
  • Node(CommonJS) → global 相当(少し特殊だが概念的にはグローバル)
  • var で宣言したグローバル変数は window.xxx に生成される(ブラウザ)

モジュール(ES Modules)

<script type="module" src="main.mjs"></script>

ここがポイント:

  • 自動で strict mode
  • top-level の thisundefined
  • ファイルごとに独立したモジュールスコープを持つ
    → top-level で const x = 1; としても window.x にはならない
  • import / export が使える
  • ブラウザでは <script type="module"> は デフォルトで defer 相当(HTML解析後に実行)

ここでは「違いの存在」を知るだけでOKです。


<<前へ(最初のJavaScriptコード)

>>次へ(執筆中)

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次