JavaScriptのスコープわからない
Comments: 4 - Date: January 9th, 2008 - Categories: JavaScript
オライリーのJavaScriptの本読んでてスコープのところでつまった。
var scope = "global";
function f() {
alert(scope);
var scope = "local";
alert(scope);
}
f();
これをfirebugで実行すると1回目のalertで「undefined」2回目のalertで「local」が表示される。
でも、関数内でvar scopeをコメントアウトすると
var scope = "global";
function f() {
alert(scope);
//var scope = "local";
alert(scope);
}
f();
2回とも「global」が表示される。
なんで?
最初のコードの変数scopeは関数外で宣言されてるからundefinedなのはわかるけど、後のコードは関数外のグローバル変数見に行ってもいいの?
----------------------------------------------------------------------------------------------------------------------------------
※追記
----------------------------------------------------------------------------------------------------------------------------------
コメントとかチャットで色々教えてもらって、たぶんわかった。
var scope = "global";
function f() {
alert(scope);
var scope = "local";
alert(scope);
}
f();
こう書いても実行時の解釈は
var scope = "global";
function f() {
var scope; // 関数内スコープ変数scopeが定義される
alert(scope); // 関数内スコープ変数が参照されるため、もちろん未定義値(undefined)が返される
scope = "local"; // 関数内スコープ変数scopeに"local"をセット
alert(scope); // local
}
f();
ってなるらしい。
f()を呼び出すときに初めて「function f()〜〜」の上から順番に読み込むんだと思ってたけど、違うみたい。
f()を呼ぶときにはもうf関数は定義済み。
関数内に目的の変数名のローカル変数が無いと同じ名前のグローバル変数探しに行く。
ってことでいいのかな。
よくわかりました。
http://blog.wozozo.org/archives/80/trackback
Comment by mattn - 2008/1/9 Wednesday @ 19:07:04
関数が実行前に評価された段階でvar scopeは評価されてしまうので、1個目のalertで使っているscopeは既に「宣言済み、かつ未初期化」な関数内スコープ変数として処理されます。
目的(global,local)の動作とするならば、以下の様にするのが良いかと思います。
var scope = “global”;
function f() {
alert(scope);
this.scope = “local”;
alert(scope);
}
f();
Comment by mal_blue - 2008/1/10 Thursday @ 1:49:16
mattn さん
それだと、f(); の後に alert(scope); すると「local」になっちゃいますが、いーんでしょーか。
Comment by e_s_jp - 2008/1/10 Thursday @ 2:29:48
私もこの正月にオライリーのJavaScriptの本で同じとこ読んでました。
1回目のalertで「undefined」2回目のalertで「local」になる理由は、第5版(日本語)の本ではP.52-P.53に解説があります。
ローカル変数は関数全体で有効になるので、f()の最初の「alert(scope);」のscopeは「var scope = “local”;」があるために、ローカル変数のscopeを参照してしまいます。でも値「”local”」は次の行で代入されるので、最初のalertの段階ではローカル変数scopeはundefinedということですね(「”local”」がまだ代入されていないから)。
Comment by e_s_jp - 2008/1/10 Thursday @ 2:56:20
よく読み返したら、変数のスコープの内容をやや誤解しているのかも。
簡単に説明すると、関数内のローカル変数がグローバル変数で定義されたものと同じ名前の場合、関数内のローカル変数を優先します。(最初のコード)
関数内のローカル変数で定義していない変数名を参照しようとすると、グローバル変数にまで探しに行って、参照してくれます。(後のコード)
ローカル変数とグローバル変数を探しても変数名が無い場合には未定義となります。
Leave a comment