3

フロントエンドプログラミング初心者です。jQuery を学習していたときに、この問題に遭遇しました。これが私のコードです:

<script type="text/javascript">
$(document).ready(function(){
  var msg ="hi";
  $("#test1").click(function(){alert(msg)});
  msg ="hello";
  $("#test2").click(function(){alert(msg)});
});
</script>
</head>
<body>
  
<button id="test1">test1</button>
<button id="test2">test2</button>

このコードを実行すると、両方のアラートで「hello」が出力されます。クリック時の最初のボタンを除いて、「こんにちは」で警告する必要があります。なぜこのように振る舞うのですか?これは正しい動作ですか?スコープの制約のためですか?

4

5 に答える 5

5

You are having a scoping issue.

By the time you get to the point of the code that you actually click msg === "hello"

于 2012-09-20T18:54:28.593 に答える
2

msgハンドラ コードが実行されているときの値は「hello」です。

または、ハンドラー関数にデータとして渡してアクセスすることもできます。

$(document).ready(function(){
  var msg ="hi";
  $("#test1").click({msg: msg}, function(e){alert(e.data.msg)});
  msg ="hello";
  $("#test2").click({msg: msg}, function(e){alert(e.data.msg)});
});

デモ: http://jsfiddle.net/h36pf/

于 2012-09-20T19:25:23.893 に答える
1

ここにはほとんど正しい説明がたくさんありますが、驚いたことに、ここで重要な概念である閉鎖を捨てた人は誰もいません。

基本的に何が起こっているかというと、2 つの関数を宣言すると、それらが宣言されたスコープが Closure になります。つまり、そのクロージャ内の変数は引き続き関数で使用できます。言い換えると:

$(document).ready(function(){
    // this begins a closure
    var msg ="hi";
    // you are simply declaring a function here, not calling it
    $("#test1").click(function(){alert(msg)});
    msg ="hello";
    // ditto
    $("#test2").click(function(){alert(msg)});
    // the end of the closure...msg has the value "hello"
});

その後、しばらくすると、クリック イベントが呼び出されます。クリック イベントに関連付けられている関数は、引き続きクロージャにアクセスできます (内部の値msgは「hello」です)。

クロージャ内で変数の値を「キャプチャ」する従来の方法は、「即時呼び出し関数式」(IIFE)を作成することです。基本的に、これは、変数の即時値を含むまったく新しいクロージャーを作成するものと考えることができます。次のように IIFE を使用するようにコードを書き直すことができます。

$(document).ready(function(){
    // this begins a closure
    var msg ="hi";
    // the following creates an anonymous function with a single parameter
    // AND invokes it immediately, creating another closure in which the
    // value of msg1 is "hi".
    (function(msg1){
        $("#test1").click(function(){alert(msg1)});
    })(msg);
    msg ="hello";
    // ditto
    (function(msg2){
        $("#test2").click(function(){alert(msg2)});
    })(msg);
});

これにより、何が起こっているのか、探しているものを取得する方法が少し明確になることを願っています.

于 2012-09-20T19:15:02.493 に答える
1

ドキュメントの準備ができたら、JavaScript コードが実行されます。この時点で、クリック関数は 2 つのボタンにバインドされ、msg最初に hi に設定され、次に次の行が実行されmsgて hello で上書きされます。
クリックがトリガーされた時点msgで既に上書きされているため、hello が出力されます。

ただし、これは正しく、期待される動作です。この問題は、2 つの変数を使用するか、クリックの瞬間に (クリック関数で) 設定することで解決できます。

于 2012-09-20T18:56:31.353 に答える
0

これは意図した動作です。多くの場合、直感的ではありませんが、JavaScript がどのように機能するかです。意図した結果を得る最も簡単な方法は、次のような関数を使用することです。

$(document).ready(function(){
  var msg ="hi";
  $("#test1").click(getCallback(msg));
  msg ="hello";
  $("#test2").click(getCallback(msg));
});

function getCallback(msg){
    return function(){
        alert(msg);
    }
}

内のmsgパラメーターには、呼び出しごとgetCallbackに個別のmsg変数があり、個別の呼び出しごとに正しい値を維持します。

于 2012-09-20T19:00:45.940 に答える