[Javascript]letとconst


varキーワードとして宣言された変数の問題


繰り返し宣言を許可


 varキーワードは変数の繰り返し宣言を許可するため、最初に宣言した変数の値が変更される副作用があります.
// Allow duplicate declaration
var x = 1;
var y = 2;

var x = 3;

console.log(x);
console.log(y);

[실행결과]
3
2

関数レベルスキャン(function-level scope)


 varキーワードとして宣言された変数は、関数のコードブロックのみを領域スキャンとして使用します.したがって,予想外のグローバル変数反復宣言も出現する.
// function level scope
var i = 15;

for (var i = 1; i < 10; i += 2) {
  console.log(i); // 1 3 5 7 9
}

console.log(i); // 11

変数の移動


 変数宣言がコードのフロントエンドに昇格したように、変数反発(variable hoisting)によってvarキーワードとして宣言された変数は、変数宣言の前に参照することができる.
// variable hoisting
console.log(animal); // undefined

animal = 'red panda';

console.log(animal); // 'red panda'

var animal;
宣言前に変数を参照してもエラーは発生しませんが、プログラムフローで一致せず、読み取り可能性が低下します.

📌  varキーワードの欠点を補うために、ES 6はletとconstを導入した.

letキーワード


重複宣言の禁止


 varとは異なり、letが変数を繰り返し宣言するとSyntaxErrorになります.
// Not allow duplicate declaration
let subject = 'Quantum physics';

let subject = 'Electromagnetics'; // SyntaxError

ブロックレベルスキャン


 letキーワードとして宣言された変数は、すべてのコードブロックを領域スキャンと認定するブロックレベルスキャンに従う(block-level scope).
// block-level scope
let i = 5;

function foo() {
  let i = 10;

  for (let i = 3; i > 1; i--) {
    console.log(i); // 3 2
  }

  console.log(i); // 10
}
foo();
console.log(i); // 5

変数の移動


 letとして宣言された変数の動作は、変数エスケープが発生しないようにします.
// variable hoisting
console.log(color); // ReferenceError

let color;
console.log(color); // undefined

color = 'black';
console.log(color); // 'black'
実行時までに宣言ステップが実行されますが、変数宣言に達すると初期化ステップが実行されます.初期化ステップを実行する前に変数にアクセスしようとすると、参照エラーが発生します(ReferenceError).また、スキャンの開始点から初期化段階の開始点まで変数を参照することはできず、この区間を一時死角領域(TDZ, Temporal Dead Zone)と呼ぶ.

では、本当に変数繁栄は起こっていませんか?
たとえば、
let dog = 'Shih Tzu';

{
  console.log(dog); // ReferenceError
  let dog = 'Maltese';
}
変数エスケープが発生しない場合はdog値で「Mattese」を出力する必要があります.しかし、まだエスケープが発生するため、ReferenceErrorが発生します.

constキーワード


 constは通常、定数を宣言するために使用される(constant).特徴はletキーワードとほとんど同じなので、違いを見てみましょう.

宣言と初期化


 contとして宣言された変数は、宣言と同時に初期化する必要があります.そうでない場合、SyntaxErrorが発生します.
// declaration and initialization
const a; // SyntaxError
const b = 1;
constもletと同様にブロックレベルスキャンを有し,変数エスケープが発生しないように動作する.
// variable hoisting and block-level scope
{
  console.log(x); // ReferenceError
  const x = 5;
  console.log(x); // 5
}

console.log(x); // ReferenceError

再割り当ての禁止


 var、letとは異なり、constと宣言された変数は再割り当てを禁止します.
const a = 2;
a = 4; // TypeError

ていすう


 定数とは、再割り当てを禁止する変数です.
let savings = 10000;
let totalAmount = savings + (savings * 0.3);

console.log(totalAmount);  // 13000
上のコードの0.3は意味がわかりにくいので、毒性が悪いです.変更が容易でない値であれば、再割り当てが禁止されているconstキーワードを使用した変数に割り当てることが望ましい.
定数の名前が大文字の場合、複数の単語からなり、underscore(_)に区別されたsnake caseが一般的に用いられる.
const IR = 0.3
let savings = 10000;
let totalAmount = savings + (savings * IR);

console.log(totalAmount);  // 13000

constとobject


 constとして宣言された変数に元の値が割り当てられている場合は変更できませんが、オブジェクトが割り当てられている場合は変更できます.オブジェクトは、再割り当てを必要とせずに直接変更できるプロパティです.このようにconstキーワードは再割り当てを禁止するだけで、「変わらない」という意味ではありません.
// const and object
const tomNJerry = {
  tom: 'cat',
  jerry: 'rat'
};

tomNJerry.jerry = 'mouse';

console.log(tomNJerry);

[실행결과]
{ tom: 'cat', jerry: 'mouse' }
💡 var vs let vs const
✔ES 6を使用する場合はvarは使用しません.
✔デフォルトではconstを使用し、再割り当てが必要な場合は限定害letを使用します.
✔変更されない元の値とオブジェクトに対してconstを使用します.var,letはキーワードよりも安全です.