みみぺんブログ

WEBデザイナー、エンジニア、プログラマー向けの記事を投稿します

変数宣言(var / let / const)の違いについてサンプルコード付きで解説【JavaScript初心者入門】 

JavaScriptの第一歩 変数宣言(var / let / const)について
こんにちは、かずん(@kazoonLab)です。


前回の記事では、「JavaScriptのスコープ」についてお話ししました。


今回は、スコープと密接にかかわる、「var / let / const」についてです!



かずん

この記事を読むと次のことがわかるよ!

  • var / let / constそれぞれの使い方
  • かずん流 宣言のベストなやり方



はじめに


そもそも変数とは何か、という話に関しては今回は触れません。今回は、「var / let / const」それぞれの振る舞いが、どのように異なるかを見ていきたいと思います。


変数の基礎的な部分が分からなければ、このリンクが参考になるかと思います。


それぞれの使い方

varとは

varは、古くから変数宣言に用いられてきました。


varは、以下の特徴を持ちます。
・初期化不要
・関数スコープである
・巻き上げが発生する
・再定義できる
・再代入できる


スコープについては以下の記事にて触れていますので、そちらをご覧ください。
blog.mimipen.net


それでは、例を見てみましょう。

// グローバルな変数を定義
var global;(1)
global = 'global';

function globalFunc () {
	// 関数内でローカルな変数を定義
	var local = 'local';(2)
	console.log(global); // --> global
	console.log(local); // --> local
};

console.log(global); // --> global
console.log(local); // --> (Error)(3)

// グローバル変数に再代入する
global = 'global2';
console.log(global); // --> global2

// グローバル変数を再定義する
var global = 'global3';
console.log(global); // --> global3(4)

// 巻き上げを確認する(5)
console.log(newGlobal); // --> undefined
var newGlobal = 'newGlobal';
console.log(newGlobal); // --> newGlobal;


変数の初期化とは、変数宣言と同時に値を代入する行為を指します(上記②のように)


(1)では変数宣言のみ行い、値の代入はしていません。この場合、変数globalはデフォルト値undefinedで初期化されます。


関数globalFunc()内で変数localが宣言されている(2)ため、この関数の外からは変数localは参照できません。(3)


(4)のように、varで宣言された変数は再定義できます(できてしまいます)。変数を多重に宣言することは、意図しないコードの挙動(バグ)の原因となり得ます。


また、varには「巻き上げ」という仕様があります。これは、「あるスコープの中で宣言された変数は、スコープのどの位置で宣言されようとも、スコープの戦闘で宣言されたことになる」というものです。


(5)以下の挙動は、以下のコードと同じになります。

var newGlobal;
console.log(newGlobal); // --> undefined(6)
var newGlobal = 'newGlobal';
console.log(newGlobal); // --> newGlobal;


(6)でundefinedな値を参照していますがエラーになっていません。これも、意図しない挙動といえるでしょう。


では、次にletを見ていきましょう。

letとは

letは、varの不安定な箇所を補うべく誕生しました。


letは、以下の特徴を持ちます。
・初期化不要
・ブロックスコープである
・巻き上げが発生するが、エラーになる
・再定義できない
・再代入できる


例を見てみましょう。

// 初期化せず宣言
let global;(1)
// 代入前の変数呼び出しはエラーになる
console.log(global); // --> (error)(2)
global = 'global';(3)
// 初期化して宣言
let global2 = 'global2';
console.log(global2); // --> global2
global = 'global';

if (true) {
	// ブロック(if文)の中でローカル変数を宣言
	let local = 'local'
	console.log(local); // --> local
}

// ブロックの外からは、ローカル変数は参照できない(4)
console.log(local); // --> (error);
let global3 = 'global3';
// 再定義はNG
let global3 = 'global4'; // --> (error)
console.log(global3);
let global4 = 'global4';
// 再代入はOK
global4 = 'global5';
console.log(global4); // --> global5


varと同様、初期化せず宣言した変数はundefinedで初期化されます(1)。ただし、(3)で初期化する前に変数の呼び出しをするとエラーになります(2)。ここがletとvarで異なるポイントです。


厳密にいえば、巻き上げは発生しているのですが、代入前の参照はエラーになるという仕様となっています。


(4)のように、ブロック内で宣言した変数は外から参照できません。このため、ブロック外での意図しない更新を防ぐことができます。


最後に、最も厳密な宣言「const」を見ていきましょう。

constとは

constは、letよりも厳密な変数宣言を行うべく誕生しました。


constは、以下の特徴を持ちます。
・初期化が必要
・ブロックスコープである
・巻き上げが発生しない
・再定義できない
・再代入できない(例外有り)


例を見てみましょう。

// 初期化しない変数宣言はエラー
const global; // --> (error)
const global = 'global';
// 再定義はエラー
const global = 'global2'; // --> (error)
// 再代入もエラー
global = 'global3'; // --> (error)
const global = 'global';
if (true) {
	const local = 'local';
	console.log(local); // --> local
}
console.log(local); // --> (error)


constで宣言される変数は、宣言と同時にに初期化しなければならず、また再代入・再定義できません。


またブロックスコープであるため、ブロック外からの参照もできません。巻き上げについても、宣言と


一見すると不便なように見えますが、実はとてもありがたい存在なのです。その理由を考えてみましょう。


ある変数がconstで宣言されていて、かつソースコードにエラーが発生していない場合、


「この変数は絶対にほかの場所では使われていない。また、この変数は常に最初の値のままである」


と考えることができるでしょう。つまり、ソースコードを書く人は、意図しない参照を防ぐ(しようとするとエラー)ことができます。


一方。ソースコードを読む人は、ブロック内のconst変数は常に変わらない(*)と信じて読むことができます。


まとめると、constを利用することで、書き手・読み手双方の心理的負担、また費やす時間を削減することができるのです。


(*)プリミティブな値(数字、文字列、...)は再代入できませんが、オブジェクトや配列の中の値の更新はできてしまいます

const obj = { key: 'value' };
// 中の値の更新はエラーにならない
obj.key = 'value2'; // --> (ok, { key: 'value2' })
// オブジェクトそのものの更新はエラーになる
obj = { key: 'value2'} // --> (error)

// 配列も同じ
const arr = [0, 1, 2];
arr[0] = 1; // --> (ok, [1, 1, 2])
arr = [3, 4, 5]; // --> (error)


まとめ


ここまで、var, let, constそれぞれの特徴について見てきました。


あくまで私の意見ですが、コーディング時にきちんとエラーを出してほしい、また読むときになるべく苦にならないように、


原則宣言はconstで行い、再代入の必要があればletを使う


のが良いのではないかと思います。varには別れを告げてしまいましょう。


この記事を読んでくださった方のソースコードが、よりよくなることを願ってやみません。


最後までご覧いただきありがとうございます。


この記事がいいなっと思ったら読者登録をお願いいたします♪


【ツイッターでは、仕事のことなどをつぶやいています】
技術者の方ともっと繋がりたいっす!お気軽にフォローもお願いします!
かなきち
かずん