question:1184576878で質問した者です。

また新たな疑問が出てしまいました。助けて下さい。


var x = "a";
var hoge = function(){alert(x)}

setTimeout("hoge();",3000);
setTimeout(hoge,6000);

x = x + "b";
hoge = function(){alert(x+"c")}
hoge();


「abc」「abc」「ab」と返ってくる理由が分かりません。よろしくお願いします。

回答の条件
  • 1人3回まで
  • 登録:2007/07/18 22:24:34
  • 終了:2007/07/19 10:52:35

回答(3件)

id:kn1967 No.1

kn1967回答回数2915ベストアンサー獲得回数3012007/07/18 23:24:22

ポイント100pt

まずは動作を時系列に追っていきましょう。

1)var x = "a"; 初期値セット

2)var hoge = function(){alert(x)} 関数セット

3)setTimeout("hoge();",3000); タイマーセット

4)setTimeout(hoge,6000); タイマーセット

5)x = x + "b"; xの中身が"ab"になった

6)hoge = function(){alert(x+"c")}

  このアラートが呼び出されてもxの中身に変化は一切無い。

7)hoge(); ここで1回目のアラート出力がなされる。

  ここではhogeに()が付いているので上記6)が呼び出された形となり出力はabc

8)3000経って3)でセットしたタイマーが起動

  ここでも()が付いているので6)が呼び出されて出力はabc

9)6000経って4)でセットしたタイマーが起動

  ここでは()が付いていないので事前にセットした値2)の式が用いられxの中身であるabが出力される


時系列に追っていった結果として

a)hoge はvarで定義された関数リテラルを呼び出す。

b)hoge() は最後に定義された時点での関数を呼び出す。

という違いが判ってくるかと思います。

専門用語では「関数ポインタ」と呼びますが、そこまで話だすと長くなるので、ひとまず違いがあるという点までを検証してください。

id:Lhankor_Mhy

あ、なるほど。分かりました。

2007/07/19 10:43:32
id:znz No.2

znz回答回数193ベストアンサー獲得回数252007/07/18 23:47:11

ポイント100pt

変数の評価のタイミングがわかっていないように思います。

順番に説明を付けてみたので、それぞれのタイミングでxとhogeは何を指していて、何が実行されるのかを考えてみるとわかるでしょうか。

  • var x = "a";
    • xという変数が"a"を指す。
  • var hoge = function(){alert(x)}
    • hogeという変数が「alert(x)」という処理をする関数を指す。
  • setTimeout("hoge();",3000);
    • 3000ms後に「hoge();」という処理をする。
  • setTimeout(hoge,6000);
    • 6000ms後に(この行の処理のタイミングでhogeという変数が指している)「alert(x)」という処理をする関数を実行する。
  • x = x + "b";
    • xという変数が(xという変数が指していた)"a"と"b"を「+」した文字列"ab"を指す。
  • hoge = function(){alert(x+"c")}
    • hogeという変数が「alert(x+"c")」という処理をする関数を指す。
  • hoge();
    • hogeが指す「alert(x+"c")」という処理が実行される。
    • ここでxは"ab"なので"abc"になる。
  • 3000ms後に文字列で指定された「hoge();」という処理
    • hogeが指す「alert(x+"c")」という処理が実行される。
    • ここでxは"ab"なので"abc"になる。
  • 6000ms後に「alert(x)」という処理をする関数を実行
    • ここでxは"ab"なので"ab"になる。
id:Lhankor_Mhy

分かりました。有難うございます。

2007/07/19 10:49:17
id:ardarim No.3

ardarim回答回数892ベストアンサー獲得回数1422007/07/19 01:02:38

ポイント100pt
①var x = "a";
②var hoge = function(){alert(x)}

③setTimeout("hoge();",3000);
④setTimeout(hoge,6000);

⑤x = x + "b";
⑥hoge = function(){alert(x+"c")}
⑦hoge();

最初に①~②が実行されます。


③で、3秒後に "hoge();" が評価されるようセットされますが、文字列としてセットされますので、この時点で hoge の内容が何であるかはまったく意味がありません。3秒後に文字列 "hoge();" がスクリプトとして評価され、そのときに初めて hoge が参照されます。


④で、6秒後に hoge が評価されるようセットされますが、これは文字列ではありません。この時点でhoge=function(){alert(x)}ですので、setTimeout(function(){alert(x)},6000);を実行するのと等価です。したがって、約6秒後にfunction(){alert(x)}が実行されます。


⑤で x に "ab" がセットされます。


⑥でhogeの内容がfunction(){alert(x+"c")}に置き換わります。


⑦が実行されるとき、⑥で定義されたhogeが実行されますので、⑤でセットされたxの値 "ab" + "c" がまず表示されます。


約3秒後、文字列としての "hoge();" がスクリプトとして評価されます。このとき、hogeは最後に⑥でセットされた関数内容が有効になっています。したがって、"abc" が表示されます。


約6秒後、function(){alert(x)}が実行されます。"ab"が表示されます。


したがって、「abc」「abc」「ab」という表示になります。

id:Lhankor_Mhy

理解できました。有難うございます。

2007/07/19 10:51:46

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません