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; }