strict モード

このエントリは、ECMAScript5 の strict モードについてのメモです。
コード関連は、chromeで確認しています。

# 概要

strict モードにすることで幾つかの機能を制限します。
主に

- 暗黙的なグローバル変数の禁止
- 代入不可なプロパティへの代入の禁止
- 削除できないプロパティの削除の禁止
- 関数の引数名の重複は禁止
- 8進数表記は禁止
- with 禁止
- 幾つかの識別子は予約語にするため使用禁止

などを制限します。


# 適用方法と範囲

strict モードにするには、

```javascript
'use strict';
```
の文をスクリプトの先頭か関数の先頭に追加します。

### スクリプト全体

スクリプト全体で strict モードにするには、スクリプトの先頭に追加します。
（js ファイルの先頭かインラインスクリプトの先頭）

```javascript:strict1.js
// strict モード
'use strict';
var foo1 = 'A';
foo2 = 'B';		                  // Uncaught ReferenceError: foo2 is not defined

console.log(foo1, foo2);	// 例外発生のため実行されない
```

先頭以外に追加しても strict モードにならず、非 strict モードで動作します。

```javascript:strict2.js
// 非 strict モード
var bar1 = 'A';

'use strict';
bar2 = 'B';		                   // 問題なし

console.log(bar1, bar2);	// A, B
```

strict モードはスクリプトを跨ぎません。

```javascript:strict3.js
// strict モード
'use strict';
```

```html:index.html
<!-- script タグのみ抜粋 -->
<script src="./strict3.js"></script>
<script>
    // 非 strict モード
	window.addEventListener('load', function() {
		foovar1 = 'ABC';
		console.log(foovar1);	// ABC
	} );
</script>
```

スクリプト全体で strict モードにした場合、非 strict モードのスクリプトと連結すると 非 strict モードのスクリプトが strict モードで動作してしまうため問題になります。

### 関数内

関数内で strict モードにするには関数の先頭で 'use strict'; を追加します。先頭以外に追加しても strict モードは有効になりません。

```javascript:strict4.js
// スクリプトは 非 strict モード
function func1() {
    // func1 は 非 strict モード
    f1foo = 'func1';
    console.log(f1foo);    // func1
}
function func2() {
    // func2 は strict モード
    'use strict';
    f2foo = 'func2';          // Uncaught ReferenceError: f2foo is not defined
    console.log(f2foo);    // 例外発生のため実行されない
}
```


# strict モードでの変更点

### 暗黙的なグローバル変数の禁止

var を使用しないで変数に代入するとグローバル変数になりますが、それを禁止します。つまりグローバル変数を使う場合は、var で宣言する必要があります。

```javascript
'use strict';
var foo = 111;  // 問題なし
bar = 222;       // Uncaught ReferenceError: foo is not defined
```

### 書き込み不可のプロパティへの代入禁止

```javascript
'use strict';
var obj1 = {};
Object.defineProperty(obj1, 'x', { value: 42, writable: false });
obj1.x = 100;   // Uncaught TypeError: Cannot assign to read only property 'x' of object '#<Object>'
```

### getter のみのプロパティへの代入禁止

```javascript
'use strict';
var obj2 = { get x() { return 17; } };
obj2.x = 5;   // Uncaught TypeError: Cannot set property x of #<Object> which has only a getter
```

### 拡張不可オブジェクトへの新規プロパティの割り当て禁止

```javascript
'use strict';
var fixed = {};
Object.preventExtensions(fixed);
fixed.newProp = "ohai";   // uncaught TypeError: Can't add property newProp, object is not extensible
```

### 削除できないプロパティの削除の禁止

```javascript
"use strict";
delete Object.prototype;   // Uncaught TypeError: Cannot delete property 'prototype' of function Object() { [native code] }
```

### 関数の引数名の重複は禁止

```javascript
'use strict';
function x(p1, p1) {};   // Uncaught SyntaxError: Duplicate parameter name not allowed in this context
```

### 変数の削除は禁止

```javascript
'use strict';
var obj1 = 123;
delete obj1;   // Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.
```

### 8進数表記は禁止

```javascript
'use strict';
var x = 077;    // Uncaught SyntaxError: Octal literals are not allowed in strict mode.
```

### eval 変数、arguments 変数の宣言禁止

```javascript
'use strict';
var eval = 123;   // Uncaught SyntaxError: Unexpected eval or arguments in strict mode
```

```javascript
'use strict';
var arguments = 123;   // Uncaught SyntaxError: Unexpected eval or arguments in strict mode
```

### with 禁止

```javascript
'use strict';
with (Math) {        // Uncaught SyntaxError: Strict mode code may not include a with statement
    x = cos(2)
};
```

### 幾つかの識別子は予約語にするため使用禁止

将来の拡張のためいくつかの識別子は予約語になります。

- implements
- interface
- let
- package
- private
- protected
- public
- static
- yield

```javascript
'use strict';
var interface = 100;    // Uncaught SyntaxError: Unexpected strict mode reserved word
```


# サポートするブラウザ

ECMAScript5 の strict モードをサポートするブラウザです。

|ブラウザ|
|:--|
| Firefox 4 以上 |
| Chrome 13 以上 |
| Safari 6 以上 |
| Edge 12 以上 |
| Internet Explorer 10 以上 |

http://caniuse.com/#search=strict%20mode


# 参考
https://developer.mozilla.org/ja/docs/Web/JavaScript/Strict_mode
https://msdn.microsoft.com/ja-jp/library/br230269(v=vs.94).aspx
http://www.w3schools.com/js/js_strict.asp