この記事では、ES5 で導入された Strict モードについて解説する。
Strict モードとは
デフォルトの厳格ではない JavaScript で許容されている一部の機能や書き方を制限するモードのこと。Strict モードを有効にするには、ファイルの先頭あるいは関数内の先頭で
'use strict';
function myfunc() {
'use strict';
// ...
}
あるいはダブルクウォートで
"use strict";
function myfunc() {
"use strict";
// ...
}
と記述する。
Strict モードの使用目的
Strict モードを使用する目的としては次のようなものがある。
- バグの原因になりそうな一部の記述を禁止し、エラーを発生させる。
- 将来の ECMAScript で使用される可能性のある予約語を確保する。
バグの原因になりそうな一部の記述を禁止し、エラーを発生させる
例えば、JavaScript のデフォルトのモードでは、var / let / const などのキーワードで宣言していない変数への代入は、グローバルオブジェクトの新しいプロパティの作成を意味する。
以下のサンプルを実行してみると、関数内での変数 msg への代入により、グローバルオブジェクト(window オブジェクト)に新しいプロパティ window.msg が作成されることが分かる。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>title</title>
</head>
<body>
<script src="main.js"></script>
</body>
</html>
// main.js
function myfunc() {
msg = 'Hello';
console.log(msg);
}
myfunc();
// --> Hello
console.log(window.msg);
// --> Hello
しかし、’use strict’ により Strict モードを有効にすると、エラー「Uncaught ReferenceError: msg is not defined」が発生する。
function myfunc() {
'use strict';
msg = 'Hello';
console.log(msg);
}
myfunc();
// --> Uncaught ReferenceError: msg is not defined
これにより、
- var / let / const などのキーワードを付け忘れたことにより、誤ってグローバルな変数を定義してしまうこと
- 変数名の綴りを間違えて代入文を実行してしまうこと
がエラーになり、このようなミスを防ぐことができる。
将来の ECMAScript で使用される可能性のある予約語を確保する
Strict モードでは、将来の ECMAScript で使用される可能性のある予約語を変数として使用できいない。使用するとエラーを発生する。(参考:MDN)
'use strict';
const implements = 100;
// --> Uncaught SyntaxError: Unexpected strict mode reserved word
モジュールでは常に Strict モード
モジュール内では “use strict”; を記述しなくても常に Strict モードが適用される。次のサンプルでは、変数 msg を宣言なしで使用しているためエラーとなっている。
デフォルトのモードであれば、グローバルオブジェクト(window オブジェクト)にプロパティが追加されエラーにはならないはずだが、Strict モードが適用されているため、エラーとなっている。
// moduleA.js
function myfunc() {
msg = 'Hello';
console.log(msg);
}
myfunc();
// --> Uncaught ReferenceError: msg is not defined
class 内では 常に Strict モード
class の constructor やメソッドの中は常に Strict モードが適用される。そのため下のサンプルでは、class の constructor やメソッドの内部で定義した関数配下の this は undefined となり、一方 class 外で定義した関数配下の this は、Strict モードが適用されないのでグローバルオブジェクト(window オブジェクト)となっている。
function outerFunc(msg) {
console.log(msg, this);
}
class MyClass {
constructor() {
function f() {
console.log('constructor1:', this);
}
f();
outerFunc('constructor2:');
}
method() {
function f() {
console.log('method1:', this);
}
f();
outerFunc('method2:');
}
}
const instance = new MyClass();
instance.method();
// constructor1: undefined
// constructor2: Window {window: Window, self: Window, document: document, name: "", location: Location, …}
// method1: undefined
// method2: Window {window: Window, self: Window, document: document, name: "", location: Location, …}