やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

JS(ES6)の変数宣言 var, let, const

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グローバル変数になってしまう。ブロックスコープにしたかったのにletconstを忘れてしまい、グローバル変数になってしまう事故が起こりうる。

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

参考