クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【JS】変数 varとletとconst(再代入、再宣言の挙動の違い)

ES2015から新しく加わった変数letconst。なんとなく新しいから使おう、良いものらしいから使おう、というのもアレなので、挙動の違いを体験してみる。

【目次】

※参考:【HTML、CSS、JSの書式】これを読めばコードが読める!書ける!まとめ!(基本5+応用1記事) - クモのようにコツコツと

変数var、let、constの違い

一番大きな違いは再代入、再宣言です。

変数名 再代入 再宣言
var
let ×
const × ×

(他に「巻き上げ」の挙動の違いもありますが、それはまた改めて…)

※参考:ES6時代の巻き上げ(hoisting) - Qiita

「再代入」「再宣言」とはなにか?具体例を見てみましょう。

varは再代入も再宣言もできる

まずはなんでもありのvarから。慣れ親しんだ変数です。

年号は何?ボタンを押してみてください。

See the Pen hensu_01 by イイダリョウ (@i_ryo) on CodePen.

「昭和!」「平成!」「令和!」というアラートが立ち上がります。

もうすぐ新年号なので年号を値に入れてみました。コードを見ていきます。

//ボタン取得
const btn = document.querySelector(".btn");

//クリックイベント
btn.addEventListener('click', function(){  
  //処理
}, false);
  • 変数btnでHTML上の要素(class名.btn)を取得
  • 変数btnにクリックイベントを設定

クリックイベントの中に処理を書いていきます。中身はこちら。

  //宣言 & 代入
  var nengo = "昭和!";
  alert(nengo);

  //再代入
  nengo = "平成!";
  alert(nengo);

  //再宣言
  var nengo = "令和!";
  alert(nengo);
  • varで変数nengoを宣言し、値に「昭和!」を代入。
    アラートでnengoを表示(昭和!)
  • 変数nengoに値「平成!」を再代入。
    アラートでnengoを表示(平成!)
  • varで変数nengoを再宣言し、値に「令和!」を代入。
    アラートでnengoを表示(令和!)

一つ目は変数の宣言と代入を同時に行っています。普段よく書く書き方だと思います。

二つ目は変数の前にvarがありません。これは変数の再代入です。値が上書きされます。

三つ目は再びvarがつきます。これは変数の再宣言です。同じ名前の変数を宣言し、違う値を入れているのでこちらも値が上書きされます。

letは再代入はできるが再宣言はできない

次はlet。ボタンを押してみてください。

See the Pen hensu_02 by イイダリョウ (@i_ryo) on CodePen.

「昭和!」「平成!」「平成!」おや?令和が出ませんね…。コードはこちら。

  //宣言 & 代入
  let nengo = "昭和!";
  alert(nengo);

  //再代入(OK)
  nengo = "平成!";
  alert(nengo);

  //再宣言(エラー)
  //let nengo = "令和!";
  alert(nengo);
  • letで変数nengoを宣言し、値に「昭和!」を代入。
    アラートでnengoを表示(昭和!)
  • 変数nengoに値「平成!」を再代入。
    アラートでnengoを表示(平成!)
  • letで変数nengoを再宣言し、値に「令和!」を代入。
    (エラーになるのでコメントアウトした)
    アラートでnengoを表示(平成!)

先ほどと同じ形ですが変数がvarではなくletです。この状態だとエラーになって処理(アラート)が実行されません。

原因は「再宣言」にあります。letは同じ名前の変数を再宣言することができません。この再宣言をコメントアウトするとアラートが立ち上がります。

3個目のアラートは「再代入」の値を表示しているので「平成!」になるわけです。

constは再代入も再宣言もできない

最後はconst。ボタンを押してください。

See the Pen hensu_03 by イイダリョウ (@i_ryo) on CodePen.

「昭和!」「昭和!」「昭和!」連呼していますね。。昭和への思いが強そうです。コードはこちら。

  //宣言 & 代入
  const nengo = "昭和!";
  alert(nengo);

  //再代入(エラー)
 // nengo = "平成!";
  alert(nengo);

  //再宣言(エラー)
  //const nengo = "令和!";
  alert(nengo);
  • constで変数nengoを宣言し、値に「昭和!」を代入。
    アラートでnengoを表示(昭和!)
  • 変数nengoに値「平成!」を再代入。
    (エラーになるのでコメントアウトした)
    アラートでnengoを表示(昭和!)
  • constで変数nengoを再宣言し、値に「令和!」を代入。
    (エラーになるのでコメントアウトした)
    アラートでnengoを表示(昭和!)

constも元の形のままだとエラーで処理(アラート)が実行されません。

constは「再代入」も「再宣言」もできないため、どちらもコメントアウトにするとアラートが動きます。

3つのアラートはすべて最初に宣言&代入した値を表示しているため昭和連呼になったわけです。

「再言言」「再代入」をエラーにすることで事故を防ぐ

なぜ「再言言」「再代入」でエラーになるのでしょう。エラーにするメリットは?

変数の値を変えることは普通はあまりありません。例えば円周率は(今は)3.14だし、消費税率は(今は)1.08です。

消費税を定義してくて変数zeiを宣言し1.08を代入します。

//消費税
var zei = 1.08;

//価格
var kakaku = 1000

//合計
var kei = (kakaku * zei) //1,080円

もし違う場所で全く同じ変数名で500と宣言されたらどうなるでしょう。

//消費税
var zei = 1.08;

//同名の別の変数
var zei = 500; //変数再宣言=値が上書きになる


//価格
var kakaku = 1000

//合計
var kei = (kakaku * zei) //500,000円!!

こんな請求書されたら目ん玉飛びでちゃう!!

同名の別の変数zeiの再宣言によって最初のzeiの値が上書きしてしまったわけです。

こうした事故を防ぐ目的でletconstが生まれました。(他のプログラミング言語ではもともとあった概念)

letとconstの使い分け

「再言言」ができないlet、「再代入」も「再宣言」もできないconst。この二つはどう使い分ければいいでしょう。

基本的にはconstでいいと思います。ただ、for文の条件の中の変数iは再代入したいのでletにします。

例えばこれは従来の変数varを使ったfor文です。

See the Pen hensu_04 by イイダリョウ (@i_ryo) on CodePen.

ボタンを押すと「昭和!」を5回連呼します。

  for (  var i = 0;  i < 5;  i++  ) {
 alert("昭和!"); //昭和が5回 
}  

これをletにしても…

See the Pen hensu_05 by イイダリョウ (@i_ryo) on CodePen.

変数iの数値が再代入されるので挙動は変わりません。

  for (  let i = 0;  i < 5;  i++  ) {
 alert("昭和!"); //昭和が5回 
}  

これをconstにすると…

See the Pen hensu_06 by イイダリョウ (@i_ryo) on CodePen.

変数iの数字が再代入されないため、アラートが1回しか実行されません。

for (  const i = 0;  i < 5;  i++  ) {
 alert("昭和!"); //1回しか実行されない 
}  

まとめ

コードが増えてくると変数の重複に気付きにくくなります。 varのときは問答無用に値が上書きされていました。

エラーで処理が実行されず、ブラウザのデベロッパーツールを見るとエラーの場所がわかる。これで不測の事態が起こりにくくなります。

挙動の違いが体験できたので、私もこれからは変数にconstletを使っていきたく思います。それではまた!


※参考:ネイティブJSやってみたシリーズ
qiita.com