(初心者向け) JavaScript の Strict モードの概要

#Strict Mode とは
Strict モードを使用すると以下のような利点がある。ただし、**Strict モードはすべてのブラウザで同じようにサポートされているとは限らないので注意すること。**

- JavaScript の機能としてはエラーではないが、落とし穴になる項目をエラーにして バグの発生を抑える。
- JavaScript の最適化を困難にする誤りを修正する。
- 将来の ECMAScript で予定されている構文(キーワードを変数名として使用するなど) を禁止して、将来の環境での動作を修正なしで容易にする。

Strict Mode はスクリプトや関数の先頭で文字列 **'use strict';** を追加することで有効になる。
JavaScript は Java や C に似ているが、動作がこれらと違う所がある。Strict モードを使うと、これらにより近くなるので、これらの言語の経験者は、Strict モードを使ったほうが安全である。

[さらに詳しくはこちらで (developer.mozilla.org) ..](https://developer.mozilla.org/ja/docs/Web/JavaScript/Strict_mode)


#サンプル

このサンプルは、Strict モードのすべての機能を紹介するサンプルではないので注意すること。

##関数ごとの Strict Mode
Strcit Mode はスクリプト全体だけでなく、関数レベルでの適用もできる。

```JavaScript
/* Strict Mode 関数 */
function strict() {
  // 関数レベル strict mode 文法
  'use strict';
  function nested() { return "ここでも Strict Mode."; }
  return "Strict Mode 関数  " + nested();
}

// 他の関数は非 Strict Mode になる。
function notStrict() {
  if (is_strict()) {
    return "非 Strict Mode";
  }
  else {
    return "Strict Mode";
  }
}
``` 

##代入だけでグローバル変数を作成できない
JavaScript では、var や let を使わず変数に値を代入すると、他に同じ名前の変数がなければ、その変数はグローバルになる。

Strict Mode では、このような変数を作ることができなくなり、必ず var などが必要になる。これにより、意図せず関数内で、グローバル変数を作ることができないので、コードの安全性が高くなる。

```JavaScript
'use strict';
// Strict Mode では偶発的にグローバル変数を作成できない。(var が必要)
// この例では、RefernceError が発生する。
try {
  mistypedVaraible = 17;
}
catch (e) {
  console.log(e.name);  // 'RefernceError' と表示される。
}
```



##意図せずエラーが起こらないケース
非 Strict Mode の場合、以下のケースは**何も起こらず無視される。** Strict Mode では TypeError 例外が発生するので、よりコードの安全性が高くなる。これらの他にも同様のケースは多数あるので、[developer.mozilla.org](https://developer.mozilla.org/ja/docs/Web/JavaScript/Strict_mode) で確認してほしい。

- 非 Strict Mode では、NaN に値を代入してもエラーにならない。
- 非 Strict Mode では、オブジェクトで、getter しか定義されていないプロパティに値を代入してもエラーにならない。
- 非 Strict Mode では、オブジェクトリテラル内の同名のプロパティは最後に定義されたものが有効になる。

```JavaScript
'use strict';
// NaN は書き込み不可のグローバル変数だが、非 Strict Mode では何も起こらない。
try {
  NaN = null;
}
catch (e) {
  console.log(e.name);  // 'TypeError' と表示される。
}

// getter だけしか定義されていないプロパティへの代入。
try {
  var obj2 = { get x() { return 17; } };
  obj2.x = 5; // プロパティ x は getter だけなので、代入は不正な操作。
}
catch (e) {
  console.log(e.name);  // 'TypeError' と表示される。
}

// オブジェクトリテラル内の同名のプロパティはエラーとなる。非 Strict Mode では最後に定義されたものが有効になる。
try {
  var o = { p:1, p:2 };
}
catch (e) {
  console.log(e.name);  // 'TypeError' と表示される。
}
```




##予約されたキーワードの変数名として使用するとエラーになる
Strict Mode では将来の ECMAScript 仕様で予約された下記キーワードと同じ名前を使うと SyntaxError になる。

```JavaScript
'use strict';
// private, package, protected は予約されている。
var private = 9;

function package(protected) {
  return private + protected;
}

var n = package(1);

console.log(n);
```

実行例

```
user@ubuntu:~/workspace/node/JavaScript/Syntax$ node StrictFuture.js
/home/user/workspace/node/JavaScript/Syntax/StrictFuture.js:14
var private = 9;
    ^^^^^^^

SyntaxError: Unexpected strict mode reserved word
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:152:10)
    at Module._compile (module.js:605:28)
    at Object.Module._extensions..js (module.js:652:10)
    at Module.load (module.js:560:32)
    at tryModuleLoad (module.js:503:12)
    at Function.Module._load (module.js:495:3)
    at Function.Module.runMain (module.js:682:10)
    at startup (bootstrap_node.js:191:16)
    at bootstrap_node.js:613:3
user@ubuntu:~/workspace/node/JavaScript/Syntax$
```

##with 文は文法エラーとなる
次のサンプルは、with 文があるので、 SyntaxError となり実行できない。

```JavaScript
'use strict';

var obj = { a:1, b:4, c:"C" };

with (obj) {  // Strict Mode では SyntaxError になる。
  console.log(a);
  console.log(b);
  console.log(c);
}
```

実行例

```
user@ubuntu:~/workspace/node/JavaScript/Syntax$ node StrictWith.js
/home/user/workspace/node/JavaScript/Syntax/StrictWith.js:15
with (obj) {  // Strict Mode では SyntaxError になる。
^^^^

SyntaxError: Strict mode code may not include a with statement
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:152:10)
    at Module._compile (module.js:605:28)
    at Object.Module._extensions..js (module.js:652:10)
    at Module.load (module.js:560:32)
    at tryModuleLoad (module.js:503:12)
    at Function.Module._load (module.js:495:3)
    at Function.Module.runMain (module.js:682:10)
    at startup (bootstrap_node.js:191:16)
    at bootstrap_node.js:613:3
user@ubuntu:~/workspace/node/JavaScript/Syntax$
```

##結論
安全なコードを書くために Strict モードを使用したほうが良い。
無条件に Strict モードを過信せず、ブラウザなどのサポート状況を確認して使う必要がある。

終わり