在子函数中访问循环迭代?

时间:2010-01-19 18:19:51

标签: javascript google-maps for-loop closures increment

我正在使用Google Maps API在地图上绘制多个点。但是,在下面的点击事件函数中,i始终设置为4,即迭代循环后的值:

// note these are actual addresses in the real page
var addresses = new Array( "addr 1", "addr 2", "addr 3", "addr 4" );

for (var i = 0; i < addresses.length; i++) {
    geocoder.getLatLng(addresses[i], function(point) {
        if (point) {
            var marker = new GMarker(point);
            map.addOverlay(marker);
            map.setCenter(point, 13);

            GEvent.addListener(marker, "click", function() {
                // here, i=4
                marker.openInfoWindowHtml("Address: <b>" + addresses[i] + "</b>");
            });
        }
    });
}

因此,当标记显示时,使用未定义的addresses[4]。如何将i的正确值传递给函数?

2 个答案:

答案 0 :(得分:1)

您需要在当前迭代期间生成匿名函数,以下内容应该修复它:

// note these are actual addresses in the real page 
var addresses = new Array( "addr 1", "addr 2", "addr 3", "addr 4" ); 

for (var i = 0; i < addresses.length; i++) { 
    geocoder.getLatLng(addresses[i], function (current) { 
        return function(point) { 
            if (point) { 
                var marker = new GMarker(point); 
                map.addOverlay(marker); 
                map.setCenter(point, 13); 

                GEvent.addListener(marker, "click", function() { 
                    // here, i=4 
                    marker.openInfoWindowHtml("Address: <b>" + addresses[current] + "</b>"); 
                }); 
            }
        } 
    }(i)); 
} 

B //注意这些是真实页面中的实际地址 var addresses = new Array(“addr 1”,“addr 2”,“addr 3”,“addr 4”);

for(var i = 0; i&lt; addresses.length; i ++){     geocoder.getLatLng(addresses [i],function(point){         if(point){             var marker = new GMarker(point);             map.addOverlay(标记);             map.setCenter(point,13);

        GEvent.addListener(marker, "click", function() { 
            // here, i=4 
            marker.openInfoWindowHtml("Address: <b>" + addresses[i] + "</b>"); 
        }); 
    } 
}); 

}

进一步澄清
Google提供的getLatLng方法使用ajax调用来获取特定地址的lat和long。由于这是一个异步调用而不是当前线程的一部分,因此需要一个回调函数,该函数在完成ajax请求时调用。这是您指定为函数的第二个参数的匿名函数 现在,在进行ajax请求时,您的代码将继续运行,每次循环遍历数组时都会增加i的值。当你的第一个ajax调用返回时,循环已经增加到地址数组(4)的长度,所以当你的回调函数运行时,你正在检索范围内的变量i之后循环增加。

使用我编写的修补程序,您将创建一个匿名函数,该函数只接受一个参数 - current - 并返回先前的匿名函数,并将i变量替换为current变量。在循环的下一次迭代之前,使用i变量作为第一个参数,立即调用此函数。这将创建一个闭包,当调用函数时,i的当前值存储在current变量中。当我们稍后引用current变量时,我们会得到i的存储值。

我并不是很擅长解释这些事情,可能是因为我对它的理解不如js Gods那么好。最好阅读some more info on javascript closures

答案 1 :(得分:-1)

我不应该在那个循环中达到4。循环运行只要我&lt; addresses.length(为4),因此循环应该从i = 0到i = 3。