ES6からlet, constが追加された。
成果物
変数の宣言
| キーワード | 再宣言 | 再代入 | スコープ | コード例 |
|---|---|---|---|---|
| (なし) | o | o | グローバル | x = 0;, function(){ x = 0; } |
var |
o | o | グローバル or ローカル | var x = 0; or function(){ var x = 0; } |
let |
x | o | ブロック | let x = 0;, function(){ let = 0; }, { let x = 0; } ( if (1) { let x = 0; }, for (let x = 0; ...) {...} ...) |
const |
x | x | ブロック | (letと同様) |
スコープ
| スコープ | 説明 |
|---|---|
| グローバル | どこからでも参照可。 |
| ローカル | 関数内のみ参照可。function(){...} |
| ブロック | ブロック内のみ参照可。{...}, if(){...}, function(){...}, ... |
スコープが広いとカプセル化できない。変数を誤操作してしまう。名前重複してしまう。
とくにグローバルスコープは名前空間の汚染といわれバグの元になりやすい。コードの規模が大きくなるほど、変数のスコープは小さくすべき。
ベストプラクティス
"use strict";で代入式x = 0;等による暗黙のグローバル変数宣言を回避する- 原則
varは使わない - 変数宣言は基本的に
const - 再代入が必要なときだけ
letを使う
再宣言
OK
var v = 0; var v = 1;
NG
let l = 0; let l = 1; // Uncaught SyntaxError: Identifier 'l' has already been declared const c = 0; const c = 0; // Uncaught SyntaxError: Identifier 'c' has already been declared
再宣言とは、同じスコープ内で同じ変数名を宣言すること。varはできる。できてしまう。再宣言できても嬉しいことは何もない。紛らわしいだけ。let, constのように名前重複エラーになって欲しい。
再代入
OK
var v = 0; v = 1; let l = 0; l = 1;
NG
const c = 0; c = 1; // Uncaught TypeError: Assignment to constant variable.
constは初回しか代入できない。できるだけconstを使えばバグも減る。
代入式による暗黙の宣言
じつは変数を宣言する前に代入式を書くと、グローバル変数として宣言したことになってしまう。
以下の例では、変数xはグローバル変数になってしまう。ブロックスコープにしたかったのにletやconstを忘れてしまい、グローバル変数になってしまう事故が起こりうる。
x = 0;
そこで"use strict";。変数宣言をする前に代入式を書くと未定義エラーになる。
"use strict"; x = 0; // Uncaught ReferenceError: g is not defined
次のいずれかでしか書けなくなる。つまり暗黙のグローバル変数宣言を回避できる。
"use strict"; let x; x = 0;
"use strict"; let x = 0;
"use strict"; const x = 0;
varも可能。明示的なグローバルorローカル変数宣言になる。だが、もはやvarの使用はバッド・プラクティスである。使わないほうがいい。
"use strict"; var x = 0; function(){ var x = 0; }