Javascript 异步调用的变量引用问题

Javascript 异步调用的变量引用问题,javascript,Javascript,我一直在玩JavaScript,但有些东西我不太明白。我这里有一段代码: $.getJSON('data.json', function(obj) { for( var p in obj.List ) { datas['id'] = obj.List[p].ListingId; datas['area'] = area; //console.log(datas); var geoc

我一直在玩JavaScript,但有些东西我不太明白。我这里有一段代码:

$.getJSON('data.json', function(obj) {

    for( var p in obj.List )
    {               
        datas['id'] = obj.List[p].ListingId;
        datas['area'] = area;

        //console.log(datas);

        var geocoder = new google.maps.Geocoder();              
        geocoder.geocode( { 'address': datas['area'] }, function(results,status)
        {

            if(status == google.maps.GeocoderStatus.OK)
            {
                var latlng = new google.maps.LatLng(results[0].geometry.location.Ya, results[0].geometry.location.Za);

                datas['latlng'] = latlng;

                //console.log(datas);                       

            }                               
        });
     }      
});
好,现在假设for循环运行3次。如果我们取消注释第一行“console.log(datas)”并运行页面,那么在控制台中我们会看到3个“datas”对象,它们有自己的“id”和“area”。如果我在geocode回调中注释第一个“console.log(datas)”并取消注释第二个“console.log(datas)”,当我运行代码时,所有3个“datas”对象在“id”、“area”和“latlng”方面都是完全相同的。然而,我期望3个“数据”对象与它们自己的latlngs不同


有什么想法吗?

我认为数据必须声明为全局数组?有吗?

我认为这是一个范围问题。在上次运行
console.log
时,
p
变量将已引用上次obj。您需要在新范围内捕获
p

for( var p in obj.List ) { 

  (function(p) {

    datas['id'] = obj.List[p].ListingId;
    datas['area'] = area;

    geocoder.geocode( { 'address': datas['area'] }, function(results,status) {
      ...
    });

  }(p));

}

您传递给
geocoder.geocode
函数的函数何时运行?如果没有立即运行,那么for循环将在geocode函数运行之前运行所有三次。这意味着
datas['id']
datas['area']
将被设置为循环的最后一次迭代。。。在这种情况下,您需要在geocode函数的闭包中捕获数据数组

在这种情况下,您需要以下内容:

$.getJSON('data.json', function(obj) {

    for( var p in obj.List )
    {               
        datas['id'] = obj.List[p].ListingId;
        datas['area'] = area;

        //console.log(datas);

        var geocoder = new google.maps.Geocoder();              
        geocoder.geocode( { 'address': datas['area'] }, function(datas){ return function(results,status)
        {

            if(status == google.maps.GeocoderStatus.OK)
            {
                var latlng = new google.maps.LatLng(results[0].geometry.location.Ya, results[0].geometry.location.Za);

                datas['latlng'] = latlng;

                //console.log(datas);                       

            }                               
        }}(datas));
     }      
});

这可以防止for循环更新匿名函数所使用的数据变量。

我确实在某一点上将其设置为全局变量,但我不记得它已修复。太好了-修复了它!然而,我仍然不太明白为什么这会修复它。您能详细说明一下吗?
geocoder
中的回调运行时,循环已经完成,因此
p
变量将只引用最后一项,这就是为什么您需要保留对
p
的引用。我发现这个链接有更多信息,你也可以在谷歌上搜索“闭包javascript”,你会发现很多有用的东西。我必须承认,我对此也有点困惑,因为回调中没有使用
p
。这是否有可能将
数据
转换为函数范围的局部变量?如果是这样,那么你根本不需要
p
参数……啊,我想我现在明白了。我没有完全意识到地理编码器是在整个循环完成后运行的(我认为对它的异步调用是即时的)。谢谢你们两个