2023年12月2日

古い "var"

この記事は古いスクリプトを理解するためのものです

この記事の情報は古いスクリプトを理解するのに役立ちます。

新しいコードを記述する方法ではありません。

変数 の最初の章では、変数を宣言する3つの方法について述べました:

  1. let
  2. const
  3. var

var 宣言は let と同じような振る舞いをします。ほとんどの場合で letvar あるいは後の逆に置き換えることができ、期待通りに動作するでしょう:

var message = "Hi";
alert(message); // Hi

ですが、内部的には var はずっと昔から使われてきた、全く異なるものです。一般的には最近のスクリプトでは利用されていませんが、古いスクリプトには依然として潜んでいます。

このようなスクリプトに出会う予定がないのであれば、この章はスキップするか後回しにしてください。

一方で、古いスクリプトを var から let に移行する際には奇妙なエラーを避けるために違いを理解することが重要です。

“var” はブロックスコープを持ちません

var で宣言された変数は、関数スコープかグローバルスコープのいずれかです。ブロックを通って見えます。

例:

if (true) {
  var test = true; // "let" の代わりに "var" を使う
}

alert(test); // true, if の後も変数は生きています

var はコードブロックを無視するので、グローバルの test を取得します。

var test の代わりに let test を利用すると、変数は if の中でのみ見えます:

if (true) {
  let test = true; // use "let"
}

alert(test); // ReferenceError: test is not defined

ループでも同様です: var はブロック、またはループのローカルにはなれません:

for (var i = 0; i < 10; i++) {
  var one = 1;
  // ...
}

alert(i);   // 10, "i" ループ後も見え、それはグローバル変数です
alert(one); // 1, "one" はループ後も見え、それはグローバル変数です

コードブロックが関数の内側にある場合、var は関数レベルの変数になります:

function sayHi() {
  if (true) {
    var phrase = "Hello";
  }

  alert(phrase); // works
}

sayHi();
alert(phrase); // Error: phrase は未定義

上の通り、varif, for もしくは他のコードブロックを貫通します。それは、JavaScriptは長い間ブロックがレキシカル環境を持っていなかったためです。var はそれを想起させます。

“var” は再宣言を許容します

同じスコープ内で2回 let で同じ変数を宣言すると、エラーになります:

let user;
let user; // SyntaxError: 'user' has already been declared

var では何度でも変数の再宣言が可能です。var で既に宣言した変数を使用すると、var