1
function updateRoomsList() {
    //empty the rooms list
    $("#rooms").empty();
    //fetch the non-joined rooms, id and name
    $.get('JoinPart', {
        goal: 5,
        userName: $("#userName").html()
    }, function (responseText) {
        var i = 0;
        id = "";
        while (i < responseText.length) {
            if (responseText.charAt(i) == '.') {
                //Now we got the full Id of a room, lets add it
                $.get('JoinPart', {
                    goal: 6,
                    roomId: id
                }, function (responseText) {
                    roomName = responseText;
                    $("#rooms").append('<div id="room' + id + '" class="listItem"><span title="Join Room" class="joinButton">+</span><div class="listItemContent">' + roomName + '</div></div>');
                });
                id = "";
            } else {
                id = id + responseText.charAt(i);
            }
            i++;
        }
    });
}

この関数には変数がありますidalert(id);

if(responseText.charAt(i)=='.')

で計算されたIDの適切な値を取得しますが、IDの内部でelse実行すると、IDは空になります。つまり、関数では、に値がありません。このIDを取得して、$。get関数の外部の値を取得するにはどうすればよいですか。 ?alert(id);$.get""appendid

4

2 に答える 2

1

コードフローはあなたが考える順序ではありません。

            id="";

ちなみに、クロージャと呼ばれる関数内関数の前に発生しています(これはグーグルに役立ちます)。印刷ステートメントを追加します

alert("here 1");
alert("here 2"); 

クロージャーの中で、そしてその前にid="";、これは飛び出すはずです。

最も簡単な修正は、おそらくクロージャー内でスワップすることですid。これroomIdは、単純な文字列またはintであるため、値がに完全にコピーされroomId、変更された場合でも安全であるためですid(より正確にid=...は、参照を変更するだけなので、参照される値同じままですroomId。)

于 2012-08-05T15:40:45.893 に答える
1

これは、スコープが外部クロージャーであるため、内部コールバックはループidの最後に設定された最後の値への参照を取得するためです。2番目のコールバック内に変数whileのプライベートコピーが必要な場合は、次のように記述する必要があります。id$.get()

$.get('JoinPart', {goal :6, roomId :id }, (function (id) {
  return function (responseText) {
    roomName = responseText;
    $("#rooms").append('<div>' + id + '</div>');
  }
})(id));

これを行うときは、ローカル変数自体ではなく、現在の反復で持っていidた正確な値が与えられるローカル変数を使用して新しいスコープを作成します。これは、ループの最後(または実際には次の反復で)に可能です。何でもあります。idid

コンストラクト(function(arg){})(arg)は、即時呼び出し関数式と呼ばれます。この関数は、によって必要とされる新しい関数オブジェクトを返すことに注意してください。$.get()

クロージャは、別のクロージャ内で定義された関数です。クロージャは、定義上、外部関数にローカルなすべての変数にアクセスできます。後で実行するためのコールバックをに提供する場合$.get()、実際にはクロージャを使用しています。コールバックが実行されるとき(おそらく数秒後)、JSエンジンはid引き続きアクセス可能になりますが、その値は明らかに残りのコードに依存します。

後で読み取るために変数の現在のスナップショットを保存する必要がある場合は、新しいクロージャー(つまり新しいスコープ)を作成する必要があります。この目的でIIFEを使用します。IIFEは、実際のHTTPリクエストが実行される直前(つまり、が呼び出される$.get())に実行され、コールバックの最も近いスコープであるため、コールidバックが実行されるときに参照を解決するために使用されます。

次のスニペットが何を出力するかを理解することで、概念を理解しているかどうかをテストできます

function inner() {
  console.log(i);          
}

for (var i = 0; i < 3; i++) {
  inner();
  setTimeout(inner, 1000);
}​
于 2012-08-05T15:46:01.797 に答える