この現象は、JavaScript変数の巻き上げとして知られています。
関数内のグローバル変数にアクセスすることはありません。ローカルvalue
変数にアクセスしているだけです。
あなたのコードは以下と同等です:
var value = 10;
function test() {
var value;
console.log(value);
value = 20;
console.log(value);
}
test();
それでもあなたが得ていることに驚いていますundefined
か?
説明:
これは、すべてのJavaScriptプログラマーが遅かれ早かれ遭遇するものです。簡単に言えば、宣言する変数は常にローカルクロージャーの一番上に引き上げられます。したがって、最初のconsole.log
呼び出しの後に変数を宣言したとしても、それ以前に宣言したかのように見なされます。
ただし、宣言部分のみが引き上げられています。一方、割り当てはそうではありません。
したがって、最初にを呼び出したconsole.log(value)
ときは、ローカルで宣言された変数を参照していましたが、まだ何も割り当てられていません。したがってundefined
。
ここだもう一つの例は:
var test = 'start';
function end() {
test = 'end';
var test = 'local';
}
end();
alert(test);
これは何を警告すると思いますか?いいえ、ただ読むのではなく、考えてみてください。の価値はtest
何ですか?
以外のことを言ったらstart
、あなたは間違っていました。上記のコードはこれと同等です:
var test = 'start';
function end() {
var test;
test = 'end';
test = 'local';
}
end();
alert(test);
グローバル変数が影響を受けないようにします。
ご覧のとおり、変数宣言をどこに置いても、常にローカルクロージャーの一番上に持ち上げられます。
サイドノート:
これは関数にも当てはまります。
このコードを考えてみましょう:
test("Won't work!");
test = function(text) { alert(text); }
これにより、参照エラーが発生します。
Uncaught ReferenceError:テストが定義されていません
このコードは正常に機能するため、これにより多くの開発者が失敗します。
test("Works!");
function test(text) { alert(text); }
この理由は、前述のように、割り当て部分が持ち上げられていないためです。したがって、最初の例では、test("Won't work!")
が実行されたときに、test
変数はすでに宣言されていますが、まだ関数が割り当てられていません。
2番目の例では、変数の割り当てを使用していません。むしろ、適切な関数宣言構文を使用しています。これにより、関数が完全に引き上げられます。
Ben Cherryは、これに関する優れた記事を、適切にJavaScript Scoping andHoistingというタイトルで書いています。
それを読んで。それはあなたに完全な詳細で全体像を与えるでしょう。