300以上のホームページ制作案件に携わってきました。豊富な経験とお客様目線のホームページ制作、SEOを考慮した提案が強みです。茨城に寄り添ったサービスを多く展開してまいります。
  • JavaScript

  • プログラミング

【JavaScript】var / let / constのベストな使い方

【JavaScript】var / let / constのベストな使い方

こんにちは、かずん(@kazoonLab)です。

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

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

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

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

はじめに

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

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

それぞれの使い方

varとは

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

varは、以下の特徴を持ちます。

  • 初期化不要
  • 関数スコープである
  • 巻き上げが発生する
  • 再定義できる
  • 再代入できる

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

JavaScriptのスコープまとめ!【global・functional・block】

JavaScriptのスコープまとめ!【global・functional・bl…

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

// グローバルな変数を定義
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には別れを告げてしまいましょう。

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

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

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

検索

おすすめ記事

お知らせ

【お手軽パック】茨城の方限定! 50%OFFキャンペーン中。本当にいいホームページを始めやすい価格で 【お手軽パック】茨城の方限定! 50%OFFキャンペーン中。本当にいいホームページを始めやすい価格で

※ほぼ同条件の全国10,000以上のホームページの平均価格75万円の5分の1価格という意味。