298

この記事は最終更新日から1年以上が経過しています。

【JavaScript】var / let / const を本気で使い分けてみた

最終更新日 投稿日 2020年09月06日

はじめに

なんとなーくでlet/constを使い分けていたが
間違った理解をしていたので、本気で使い分ける方法をまとめてみました。

ざっくりした結論

  • ほぼ全部constで定義できる
  • 数え上げのみlet
  • varはもう使わない

参考:JavaScriptの変数宣言『let, var, const』の使い分けについて【プログラミング小話】

細かい仕様の説明

var/const/letの違い

const let var
再宣言 × ×
再代入 ×
スコープ ブロック ブロック 関数
ホイスティング エラー エラー undefined

再宣言

一度宣言した変数を、同じ変数名で宣言し直すことを再宣言といいます。
再宣言可能なvarで再宣言した場合、後に宣言した変数が適用され、
再宣言不可能なlet/constで再宣言した場合、エラーになります。
varでは、予期しない再宣言が起こりうるため危険です。

// var
var a = 0;
var a = 1; 
console.log(a) // `1`と出力される

// let
let b = 0;
let b = 1; // SyntaxError: Identifier 'b' has already been declared

// const
const c = 0;
const c = 1; // SyntaxError: Identifier 'c' has already been declared

再代入

宣言した変数に値を設定し直すことを再代入といいます。
再代入可能なvar/letで再代入した場合、値が再代入され、
再代入不可能なconstで再代入した場合、エラーになります。

// var
var a = 0;
a = 1; 
console.log(a) // `1`と出力される

// let
let b = 0; 
b = 1;
console.log(b) // `1`と出力される

// const
const c = 0;
c = 1; // Assignment to constant variable. 

スコープ

実行中のコードから参照できる範囲をスコープといいます。
const/letはブロックスコープ({}で囲われた部分 - if文やfor文など)が適用されますが、varはブロックスコープが適用されません。
※ 関数スコープ(関数宣言の{})は、var/const/letすべてに適用されます。

/*
 * var
 */
{
  var a = 0;
}
// ブロックスコープが適用されないため、ブロック外でも値の参照が可能
console.log(a); // 0


/*
 * let
 */
{
  // ブロックスコープにより、再宣言にならない。
  let a = 1;
  console.log(a); // 1
}
// letはブロックスコープであり参照できないため、varで宣言した値が参照される。
console.log(a); // 0

/*
 * const
 */
{
  const b = 2;
  console.log(b); //2
}
console.log(b) // b is not defined 

ホイスティング(変数の巻き上げ)

変数宣言が常に関数の先頭で行われたことにされる挙動をホイスティング(変数の巻き上げ)といいいます。

// var
{
  console.log(a); // undefined
  var a = 0; 
  console.log(a); // 0
}

// let / const
{
  console.log(b); // Cannot access 'b' before initialization 
  const b = 0; 
  console.log(b); // 0
}

データ型の種類と参照方法

var/const/letの変数宣言を使い分けるには、データ型の種類と参照方法を知っておく必要があります。

データ型の種類

データ型には、大きく分けてプリミティブ型オブジェクトがあります。

  • プリミティブ型(基本型)
    • Boolean - true または false
    • Number - 数値
    • String - 文字列
    • null - 空(参照を保持していない状態)
    • undefined - 未定義
    • BigInt (長整数) - 桁が多い数値(ES6)
    • Symbol (シンボル) - 一意の値(ES6)
  • オブジェクト(複合型) - プリミティブ型以外全部
    • オブジェクトリテラル
    • 配列リテラル  など

詳しい参考:データ型とリテラル - JavaScript Primer

データ型の参照

プリミティブ型とオブジェクトでは、参照方法が異なります。

プリミティブ型の場合

再代入の際に参照先が変更されます。

【図解 - 文字列の再代入の例】
Web 1920 – 1.png

オブジェクトの場合

変数に対して参照するオブジェクトが変更された際に再代入になります。
オブジェクト内のキーや値が変更されても、変数に対する参照先が変わらないため再代入にはなりません。

【図解 - オブジェクトの値変更・再代入の例】
Web 1920 – 2.png

もう一度、結論

  • ほぼ全部constで定義できる
    • オブジェクトや配列の値の変更は再代入にはならないため。
  • プリミティブ型を再代入したい場合はlet
  • varはもう使わない

新規登録して、もっと便利にQiitaを使ってみよう

  1. あなたにマッチした記事をお届けします
  2. 便利な情報をあとで効率的に読み返せます
ログインすると使える機能について

コメント

この記事にコメントはありません。
あなたもコメントしてみませんか :)
新規登録
すでにアカウントを持っている方はログイン
298