English 中文(简体)
Accessing loop iteration in a sub-function?
原标题:

I m using the Google Maps API to plot several points on a map. However, in the click event function below, i is always set to 4, i.e. its value after iterating the loop:

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

So when the marker displays it s using addresses[4] which is undefined. How do I pass the correct value of i to the function?

最佳回答

You need to generate an anonymous function during the current iteration, the following should fix it:

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

}

Further Clarification
The getLatLng method provided by Google uses an ajax call to get the lat and long for a specific address. Since this is an asynchronous call and is not part of the current thread, a callback function is required which is called on completion of the ajax request. This is the anonymous function you specify as the second parameter of the function.
Now, whilst the ajax requests are being made, your code continues to run, increasing the value of i each time the loop iterates over the array. By the time your first ajax call returns, the loop has already increased to the length of the addresses array (4), so when the your callback function runs you re retrieving the in-scope variable i after it has been increased by the loop.

With the fix I wrote, you re creating an anonymous function that takes a single argument - current - and returns the previous anonymous function with the i variable replaced with the current variable. This function is invoked right away, before the next iteration of the loop, with the i variable as it s first parameter. This creates a closure for which the current value of i is stored in the current variable at the time the function is called. When we refer to the current variable later, we re getting the stored value of i.

I m not really very good at explaining these sort of things, probably because my understanding of it isn t quite as good as the js Gods. Better to read some more info on javascript closures.

问题回答

i should not reach 4 in that loop. The loop runs so long as i < addresses.length (which is 4), so the loop should run from i=0 to i=3.





相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签