スコープはグローバルか、ローカルかの二種類です。
グローバルならば、グローバルで有効だし、ローカルならローカル全体で有効になります。言葉で書いてもピンと来ないと思うので、例を。
var globalA = "GA"; var bar = "GlobalBar"; function hoge() { var localA = "LA"; alert(globalA); // => "GA" alert(globalB); // => "GB" alert(localA); // => "LA" alert(localB); // => "undefined" alert(bar); // => "undefined" var localB = "LB"; var bar = "LocalBar"; // ※1 foo = "hogeFoo"; } function fuga() { alert(bar); // => "GlobalBar" foo = "fugaFoo"; } function piyo() { alert(foo); } var globalB = "GB";
hoge の挙動は上記コメントの通りですが、一応補足しておきます。
普通にローカルで宣言された localA はそのまま。
後から宣言された localB はfunction内部では未定義なので undefined になります。
普通にグローバルで宣言された globalA はそのまま。これは悩まないと思います。
function宣言の後にグローバルで宣言された globalB もそのまま表示。JavaScriptはスクリプト言語だから前から順番に処理されると思い込んでると勘違いする部分ですが、実際に hoge() が呼び出されるタイミングでは既に globalB の宣言は済んでいます。
面白いのが bar で、これが undefined になります。「ローカル全体で有効になる」なんて変な文言になったのはこいつの動きで、グローバルで宣言しているbarは隠蔽され、後(※1コメントの箇所)のローカルでの宣言が有効になっています。
fuga の挙動は常に GlobalBar が表示されます。 hoge が呼ばれていようと関係ありません。hoge内の bar が幾ら変更されようと、グローバルの bar には影響しません。このことから hoge の bar 宣言は上書きしているのではなく、隠蔽しているだけと言うのが判ります。
注意したいのが、スコープは暗黙でグローバルです。しかも実行されたタイミングで。
piyo の挙動は hoge も fuga も呼ばれていない場合は undefined と出力されるのではなく、エラー(foo is not defined)となります。どこでも宣言されていないので当然と言えば当然なのですが、hoge の bar と比べるとローカルの理解が深まるかと。見た目上は未宣言なのに bar はエラーではなく undefined となる事を思い出してください。hoge もしくは fuga が呼ばれたタイミングでグローバル変数としての foo が出来ます。その後ならば 直前に呼び出した方で設定される値が表示されます。
まとめると
グローバル変数はグローバルで宣言しましょう。
ローカル変数はfunctionの先頭で宣言しましょう。
宣言無しはバグの温床になります。