java scriptの変数宣言する際に注意しなければならない、varとletの違いについて解説したいと思います。因みにconstについては特にここでは取り上げませんのでご了承下さい。
##varとletの違い
var
変数を宣言し、ある値に初期化することもできる。
let
ブロックスコープのローカル変数を宣言し、ある値に初期化することもできる。
変数にはグローバル変数とローカル変数があります。
変数を関数の外側で宣言すると、その変数はその文書のどのコードからも使用できるグローバル変数となり、変数を関数の内側で宣言すると、その変数はその関数の中でしか使用できないローカル関数となります。ここまではvarとletでは違いがありません。
ブッロクスコープのローカル変数を宣言とletの説明に書いてありますが、ここが大きな違いになります。
ECMAScript2015より前のJavaScriptにはブロックスコープありません。ブロックスコープとはif、for、whileなどに用いられる{ }で囲んだ部分を指します。
次の例を見てみましょう。
if (true) {
var x = 5;
}
console.log(x); // x は 5
varで宣言したこの場合、ブロックの外からxの値を参照することができてしまいます。
なぜならECMAScript2015より前のJavaScriptにはブロックスコープがないからです。
しかしこれをletで宣言した場合は以下のようになります。
if (true) {
let y = 5;
}
console.log(y); // ReferenceError: y が定義されていない
上のコードではyはReferenceError、yは定義されていないよとコンソールに表示されました。つまりブロック内のyとブロックの外のyは別のものであると言うことです。
##変数の巻き上げ
もうひとつ、巻き上げと言われる点に違いがあります。
javaScriptには、例外を発生させることなく後に宣言した変数を参照できるというものがあります。これを巻き上げと言います。しかし、巻き上げられた変数はundefinedを返す事に注意してください。
言葉で説明しても分かりずらいと思いますので例を見てみましょう。
console.log(x); /*undefined*/
var x = 3;
この場合巻きあけがおこなわれない場合はReferenceErrorが返ってくるはずです。しかしこの巻き上げによって変数xはundefinedを返しました。
これが巻き上げと言われるものです。
ECMAScript2015では、let(const)は巻き上げは行われません。そのため変数宣言前に変数を参照するReferenceErrorになります。
実際に見てみましょう。
console.log(x);
/*ReferenceError*/
let x = 3;
このようになります。
因みにこの巻き上げは関数でも違いがあります。
関数では、関数宣言のみ巻き上げが行われ、関数式は巻き上げが行われません。
/*関数宣言*/
foo(); /*"bar"*/
function foo() {
console.log('bar');
}
/* 関数式 */
baz(); /* TypeError: baz は関数ではない*/
var baz = function() {
console.log('bar2');
};
今回はこれで以上です。
間違いなどあればご指摘ください。