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++;
        }
    });
}

在这个函数中有一个变量id,如果我alert(id);之后

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

我得到了在 中计算的 id 的正确值else,但是当我alert(id);$.getid 内部做空""时,意味着在append函数中,id没有值,我怎样才能让这个 id 具有 $.get 函数之外的值?

4

2 回答 2

1

代码流不是你想象的顺序。

            id="";

顺便说一下,在函数内函数(称为闭包)之前发生(这应该有助于您的谷歌搜索)。添加打印语句

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

在闭包之前,id="";and this 应该跳出来。

最简单的解决方法可能是在闭包中进行交换idroomId因为作为一个简单的字符串或 int,该值被完全复制到roomId,即使id更改也是安全的(好吧,更准确地说,id=...只更改引用,因此引用的值byroomId保持不变。)

于 2012-08-05T15:40:45.893 回答
1

那是因为它的作用域在外部闭包中,所以你的内部回调会引用它在循环id结束时设置的最后一个值。如果您在第二个回调中需要变量while的私有副本,则需要编写id$.get()

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

当你这样做时,你创建了一个新的作用域,它有一个局部变量id,它给出了id当前迭代中的确切值,而不是局部变量id本身,它在循环结束时(或者实际上只是在下一次迭代中)可以成为任何东西。

该构造(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 回答