JavaScript での変数定義は var を捨てて let, const を使うべき理由

  • 2019/6/17
  • JavaScript での変数定義は var を捨てて let, const を使うべき理由 はコメントを受け付けていません。

JS の変数定義では let, const を使うべし!…って何で?

JavaScript は最近色々と進化してきていますよね。

で、最近の JS の書き方としてよく言われているのは、
「変数定義では var ではなくて let, const を使うようにしろ!」
ってやつですね。
(あれ?聞いたことないですか?では、今覚えてください。)

let, const の方が新しい書き方なので、そっちを使うようにしよう…くらいな感じでもいいのですが、
せっかくなので、var と let, const がどのように違うのかを調べてみましょう。

ちなみに、以下では var と let を比較して見ていきます。
let と const は、一度定義した後に再度代入ができるかどうかの違いくらいなので、
以下では let の性質 = const の性質と思って読んでください。

var と let の違い

再定義ができるかどうか

一つ目ですが、これが最も重要な違いです。

こんな感じで…

var var_value = ’var’
let let_value = ’let’;

// 再定義!
var var_value = ’var’
let let_value = ’let’;

一度定義した変数を、再度 var, let で定義すると

SyntaxError: Identifier ’let_value’ has already been declared

var の方は何のエラーも無く、新しい値が代入されますが、
let では再度定義した時点で怒られます。

let では、ある変数名を上の方で使っていることを忘れて、
間違って再度定義するミスを起こさないように、このような仕様になっているのですね。

ちなみに、当然ですが、定義でなくて再代入であれば問題無くできます。
(const は再代入できないようにする宣言なので、const ではできません)

var var_value = ’var’
let let_value = ’let’;

// 再代入
var_value = ’var’
let_value = ’let’;

スコープの違い

二つ目はスコープの違い。
スコープとは「変数が見える範囲」のことですね。

これは深く考えずに、とりあえずサンプルを見た方がいいでしょう。

(function () {

  {
    var var_value = ’var’;
    let let_value = ’let’;
    const const_value = ’const’;

    console.log(’-----ブロック内-----’);
    console.log(’ブロック内の var の型 = ’ + typeof var_value);
    console.log(’ブロック内の let の型 = ’ + typeof let_value);
    console.log(’ブロック内の const の型 = ’ + typeof const_value);
  }

  console.log(’-----ブロック外-----’);
  console.log(’ブロック外の var の型 = ’ + typeof var_value);
  console.log(’ブロック外の let の型 = ’ + typeof let_value);
  console.log(’ブロック外の const の型 = ’ + typeof const_value);

})();

console.log(’-----関数外-----’);
console.log(’関数外の var の型 = ’ + typeof var_value);
console.log(’関数外の let の型 = ’ + typeof let_value);
console.log(’関数外の const の型 = ’ + typeof const_value);

ちなみに、console.log の中で、直接値を出力するのではなくて、typeof を使用しているのは、
未定義の変数から値を取り出そうとするとエラーで処理が止まってしまうからです。

今回は変数に文字列を入れていますので、
変数がきちんと存在していれば string で、
存在しない変数に対して typeof をすると undefined になります。

これを実行すると、以下のような結果が出ます。

-----ブロック内-----
ブロック内の var の型 = string
ブロック内の let の型 = string
ブロック内の const の型 = string

-----ブロック外-----
ブロック外の var の型 = string
ブロック外の let の型 = undefined
ブロック外の const の型 = undefined

-----関数外-----
関数外の var の型 = undefined
関数外の let の型 = undefined
関数外の const の型 = undefined

ここで、ブロックとは中括弧 {} のことですね。
ブロックの中で変数を宣言しています。

で、同じブロック内でそれぞれ変数を参照した結果を見てみると、全て string になっています。
すなわち、上で宣言された変数が見えている状態ですね。
ここまでは普通に想定される動きですし、大丈夫でしょう。

では、ブロック外に出るとどうでしょうか。

var で宣言した変数は依然見えているようですが、
let, const で宣言した変数は undefined。すなわち未定義となっています。
これは、let, const は宣言した変数は、同じブロック内でしか参照できないことを表しています。

このように、変数の見える範囲を「スコープ」というのですね。
ちなみに、このようにブロックでスコープが区切られることを「ブロックスコープ」と言います。
まんまですね。

さて次に、さらにその外の関数を出るとどうでしょうか。
この場合は当然 let, const で宣言した変数は見えていません。
加えて、 var で宣言した変数も見えなくなりましたね。

つまり、var は関数でスコープが区切られる、「ファンクションスコープ」ということです。

※ちなみに、変数はスコープの外に出ると見えなくなりますが、
外で宣言された変数はスコープの中に入っても見ることができます。

つまり、

(function () {
  let let_value = ’let’;

  {    
    console.log(’ブロック内の let の型 = ’ + typeof let_value);
  } 
})();

これは

ブロック内の let の型 = string

と出力されます。

スコープは「影響範囲が外に広がっていかないようにする」機能だと思うとわかりやすいですね。

グローバル変数の、window オブジェクトへの追加

三つ目はグローバル変数の影響範囲です。

グローバル変数とは、どこからでも参照ができる変数ですね。
先ほどのスコープの話を考えれば、一番外側のスコープ、全てのブロックや関数の外側に書けば良いということです。

さて、そのグローバル変数として、ブラウザが予め用意しているものに、 window というオブジェクトがあります。
window オブジェクトには、今開いているページの情報やブラウザのサイズの情報など、様々な情報が格納されています。

さて、その window オブジェクトとは全く関係ないところで、
グローバル変数をこちらから定義してみますと…

var var_value = ’var’;
let let_value = ’let’;
const const_value = ’const’;

console.log(’window オブジェクトの var = ’ + window.var_value);
console.log(’window オブジェクトの let =’ + window.let_value);
console.log(’window オブジェクトの const = ’ + window.const_value);

上を実行した結果がこちら

window オブジェクトの var = var
window オブジェクトの let =undefined
window オブジェクトの const = undefined

なんと、なぜか var でグローバル変数を宣言した場合は、window オブジェクトから参照できてしまいます!
それだけと言えばそれだけですし、そもそもグローバル変数を使うのが云々という話もありますが、
意外な挙動ではあるのではないでしょうか。

var を使わない理由…それは影響範囲を狭くするため!

さて、ここまでで、 var と let & const との違いを見てきました。

すでにお気づきの方もいらっしゃるかと思いますが、
どれも var ではできていたことが let, const ではできなくなっているのですね。

これは、変数定義に関連するミスを極力減らすため、
コードを書く人が見なければならない範囲を減らす、と言う効果があります。

var を使っていたときには発生していた、思わぬ事故を let, const を使用することで防ぐことができるのですね!

皆さんも、JS での変数定義は let, const を使う!と覚えておいてくださいね。

Takato Ezaki

Takato Ezaki小中高の塾講師からエンジニア

投稿者プロフィール

福岡で Web 系のエンジニアをしています。

中高の理科教師免許を取り、起業に 2 年間トライした後エンジニアの道へ入りました。

化学反応の中では Belousov-Zhabotinsky 反応が大好きです。

この著者の最新の記事

関連記事

コメントは利用できません。

募集中!(o゜▽゜)o

エンジャパン
求む、社長!
follow us in feedly

コッチもヨロシク!





最近のネタ!

  1. 2019-9-17

    2019年8月度社員総会&懇親会@Nagoya

    気づけば夏の暑さも去ろうとしています。そんな9月うまれのおみです。 さて!少しお時間空いてしまいま…
  2. 2019-9-16

    [JavaScript] オブジェクト & 配列のイマドキなコピー方法 (スプレッド構文)

    オブジェクトや配列のコピーってどうやって書きますか? 皆さん JavaScript 書いてますか?…
  3. 2019-9-9

    Web で物理アニメーション・その5(最終回) 「ライブラリを使おう」

    前回の回答 前回の宿題は、バウンド時の跳ね返り方を制御するんでしたね。 では回答。 [code…
  4. 2019-9-6

    第3回 倶楽部ぽじてぃぶ ~釣り~

    2019年7月13日に、第3回となる倶楽部ぽじてぃぶの活動が開催されました! 今回は、その様子をお…
  5. 2019-9-2

    2019年8月度社員総会&懇親会@Osaka

    2019年8月6日(火)、大阪社員総会&懇親会が開催されました! その様子をお届けします! 社員総…
ページ上部へ戻る

当サイトに掲載されているコンテンツ(文書、画像等)は、許可なく複製・転用等する事を禁じます。

「フェアネス方式®」(登録6150741)は、日本国内における株式会社エージェントグローの登録商標です。

当サイトでは最低限必要と考えられる場合において、会社名/サービス名/商品名などを記載している場合があります。
これらはあくまでも説明の必要性に応じて用いているものであり、各社の権利等を侵害を目的とするものではございません。
不適切と考えられる場合には、当社お問い合わせフォームよりご連絡ください。

当サイトでは®や™などの表記を省略させていただいております。