代码之家  ›  专栏  ›  技术社区  ›  DisgruntledGoat

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

  •  2
  • DisgruntledGoat  · 技术社区  · 15 年前

    我正在使用谷歌地图API在地图上绘制几个点。但是,在下面的Click事件函数中, 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] 这是未定义的。如何传递正确的值 到功能?

    2 回复  |  直到 15 年前
        1
  •  1
  •   Andy E    15 年前

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

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

    注意,这些是实际页面中的实际地址。 var addresses=新数组(“addr 1”,“addr 2”,“addr 3”,“addr 4”);

    对于(var i=0;i<addresses.length;i++){ geocoder.getlatlng(地址[i],功能(点){ 如果(点){ var标记=新的gmarker(点); map.addoverlay(标记); 地图.设置中心(点,13);

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

    }

    进一步澄清
    这个 getLatLng google提供的方法使用ajax调用获取lat和long以获取特定地址。因为这是一个异步调用,并且不是当前线程的一部分,所以在完成Ajax请求时需要调用回调函数。这是您指定为函数第二个参数的匿名函数。
    现在,在发出Ajax请求的同时,代码继续运行,增加了 i 每次循环迭代数组时。当第一个Ajax调用返回时,循环已经增加到地址数组(4)的长度,因此当回调函数运行时,您将检索范围内变量 在它被循环增加之后。

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

    我不太擅长解释这类事情,可能是因为我对它的理解不如JS诸神。读得更好 some more info on javascript closures .

        2
  •  -1
  •   D.C.    15 年前

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