Javascript 异步调用的变量引用问题
我一直在玩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
$.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
参数……啊,我想我现在明白了。我没有完全意识到地理编码器是在整个循环完成后运行的(我认为对它的异步调用是即时的)。谢谢你们两个