【JavaScript】varが非推奨な理由とlet・constとの違い

  • ES6以降に学び始めたため、letconstを使うのが当たり前だと思っていた
  • 古いコードに触れる機会があるとvarを散見するが、そもそもなぜこれが非推奨なのか正直理解してなかった

varletconstの違い

varletconst
再宣言
再代入
スコープ関数ブロックブロック
ホイスティング時の初期値undefined(設定されない)(設定されない)
グローバル宣言時のスコープグローバルスクリプトスクリプト

varが非推奨な理由

予期せぬバグを生み出す可能性があるから。

再宣言できてしまう

var x = 'x1';
var x = 'x2';
let y = 'y1';
let y = 'y2'; // Uncaught SyntaxError: Identifier 'y' has already been declared
const z = 'z1';
const z = 'z2'; // Uncaught SyntaxError: Identifier 'z' has already been declared

再代入できてしまう

var x = 'x1';
x = 'x2';
let y = 'y1';
y = 'y2';
const z = 'z1';
z = 'z2'; // Uncaught TypeError: Assignment to constant variable.

letでも同じことではある。

ブロックスコープ外からの上書き

function func() {
{
var x = 'x';
console.log(x); // 'x'
}
x = 'y';
console.log(x); // 'y'
}
  • varのスコープは関数
  • 上記の例ではブロック内で宣言したxのスコープは関数のため、ブロック外からでも上書きできている

ホイスティングによる巻き上げ

var x = 'x';
function func() {
console.log(x); // undefined
var x = 'y';
console.log(x); // 'y'
}
func();
  • varで宣言した場合、ホイスティング時にundefinedで初期化されてしまう
  • 上記の例ではグローバルコンテキストでx'x'が代入されるが、funcのコンテキストが生成されたタイミングでホイスティングされ、関数の実行前にxundefinedが代入されてしまう

グローバルオブジェクトの上書き

var console = 'x';
console.log('x'); // Uncaught TypeError: console.log is not a function
  • グローバルコンテキスト内でvarで宣言すると、グローバルスコープ (windowオブジェクトのプロパティ) に値が保持される
    • letconstはスクリプトスコープとして保持される
  • 上記の例では本来windowに生えているconsoleが上書きされ参照できていない

1

参考
  1. 【JS】ガチで学びたい人のためのJavaScriptメカニズム