JavaScript 速習チュートリアル

JavaScript の "use strict"

1. "use strict" ディレクティブ

"use strict" ディレクティブは、ECMAScript バージョン 5 (ES5) で導入された新機能です。
これは、JavaScript コードを「ストリクトモード(厳格モード)」で実行することを定義します。

これは単なる命令文(Statement)ではなく、リテラル式(Literal expression)であるため、古いバージョンの JavaScript では無視されます。
"use strict" の目的は、コードが「厳格モード」で実行されるべきであることを示すことにあります。
厳格モードを使用すると、たとえば、宣言されていない変数を使用することなどができなくなります。

2. ストリクトモードの宣言

ストリクトモードを宣言するには、スクリプトまたは関数の冒頭に "use strict"; を記述します。

スクリプトの冒頭で宣言した場合、それはグローバルスコープを持ち、そのスクリプト内のすべてのコードが厳格モードで実行されます。

2.1 スクリプト単位の例

"use strict";
x = 3.14;       // xが宣言されていないため、エラーになります

2.2 グローバルな適用例

"use strict";
myFunction();

function myFunction() {
  y = 3.14;   // yが宣言されていないため、ここでもエラーになります
}

関数の内部で宣言した場合、それはローカルスコープを持ち、その関数内のコードのみが厳格モードになります。

2.3 関数単位の例

x = 3.14;       // これはエラーになりません(関数外のため)
myFunction();

function myFunction() {
  "use strict";
  y = 3.14;   // ここではエラーになります
}

3. "use strict"; の構文

ストリクトモードを宣言するための構文は、古いバージョンの JavaScript との互換性を保つように設計されています。

JavaScript プログラムにおいて、数値リテラル(4 + 5;)や文字列リテラル("John Doe";)をコンパイルしても、副作用はありません。それらは単に存在しない変数としてコンパイルされ、消滅するだけです。
そのため、"use strict"; はその意味を「理解」できる新しいコンパイラに対してのみ効果を発揮します。

4. なぜストリクトモードが必要なのか?

ストリクトモードは、より「セキュア」な JavaScript を書くことを容易にします。
これまで許容されていた「悪い構文」を、本当のエラーに変えてくれるからです。

例えば、通常の JavaScript では、変数名をタイポ(打ち間違え)すると、新しいグローバル変数が作成されてしまいます。厳格モードではこれがエラーとなり、意図しないグローバル変数の作成を物理的に不可能にします。

また、通常の JavaScript では、書き込み不可のプロパティ(Non-writable properties)に値を代入してもエラーフィードバックは得られません。
厳格モードでは、書き込み不可のプロパティ、ゲッターのみのプロパティ、存在しないプロパティ、存在しない変数、または存在しないオブジェクトへの代入はすべてエラーをスローします。

5. ストリクトモードで禁止されていること

5.1 変数の宣言なしでの使用

宣言していない変数を使用することは許可されません。

"use strict";
x = 3.14;                // エラーになります

5.2 オブジェクトの宣言なしでの使用

オブジェクトも変数の一種です。宣言なしでの使用は許可されません。

"use strict";
x = {p1:10, p2:20};      // エラーになります

5.3 変数またはオブジェクトの削除

delete による変数の削除は許可されません。

"use strict";
let x = 3.14;
delete x;                // エラーになります

5.4 関数の削除

関数の削除も許可されません。

"use strict";
function x(p1, p2) {};
delete x;                // エラーになります

5.5 引数名の重複

パラメータ(引数)名を重複させることは許可されません。

"use strict";
function x(p1, p1) {};   // エラーになります

5.6 8進数数値リテラル

8進数の数値リテラルは許可されません。

"use strict";
let x = 010;             // エラーになります

5.7 8進数エスケープ文字

8進数のエスケープ文字も許可されません。

"use strict";
let x = "\010";            // エラーになります

5.8 読み取り専用プロパティへの書き込み

writable:false のプロパティへの書き込みは許可されません。

"use strict";
const obj = {};
Object.defineProperty(obj, "x", {value:0, writable:false});

obj.x = 3.14;            // エラーになります

5.9 ゲッターのみのプロパティへの書き込み

"use strict";
const obj = {get x() {return 0} };

obj.x = 3.14;            // エラーになります

5.10 削除不可能なプロパティの削除

"use strict";
delete Object.prototype; // エラーになります

5.11 予約語の制限

evalarguments という文字列を変数名として使用することはできません。

"use strict";
let eval = 3.14;         // エラーになります
let arguments = 3.14;    // エラーになります

5.12 with 文の禁止

"use strict";
with (Math){x = cos(2)}; // エラーになります

5.13 eval() のセキュリティ制限

セキュリティ上の理由から、eval() は呼び出し元のスコープに変数を生成することができません。

"use strict";
eval ("x = 2");
alert (x);      // 宣言されていないためエラーになります

また、eval() 内で varlet キーワードを使用して変数を宣言することもできません。

"use strict";
eval ("var x = 2");
alert (x);    // エラーになります

6. 関数内での this の挙動

ストリクトモードでは、関数内の this キーワードの挙動が変わります。

this キーワードは、その関数を呼び出したオブジェクトを参照します。
オブジェクトが指定されていない場合、厳格モードでは undefined を返し、通常モードではグローバルオブジェクト(window)を返します。

"use strict";
function myFunction() {
  alert(this); // "undefined" とアラートが表示されます
}
myFunction();

7. 将来への備え

将来の JavaScript バージョンで予約されているキーワードは、厳格モードで変数名として使用することができません。
これらには以下が含まれます。

  • implements
  • interface
  • let
  • package
  • private
  • protected
  • public
  • static
  • yield
"use strict";
let public = 1500;      // エラーになります

8. 注意事項

"use strict" ディレクティブは、スクリプトまたは関数の冒頭にある場合のみ認識されます。途中に記述しても効果はありませんので注意してください。