Javascript - variable scope in event handler
Can someone clarify the my understanding of variable scope within event handlers? Take a look at the code below:
var address = new Array();
address[0] = '1 Smith Street';
address[1] = '2 Smith Street';
for(var rownum=0; rownum<=address.length; rownum++)
{
if(address[rownum])
geocoder.geocode( {'address': address[rownum]}, geocodeCallBack);
}
function geocodeCallBack(results, status)
{
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
title: results[0].formatted_address
});
google.maps.event.addListener(marker, 'click', function(){
var infowindow = new google.maps.InfoWindow({
content: marker.title
});
// how come this event handler knows the marker variable references the marker variable declared about 10 lines above?
infowindow.open(map, marker);
});
}
For most people, this code seems straight-forward. It plots two markers on google maps. When you click on the first marker, it shows the address '1 Smith Street'. When you click on the second marker, it shows the address '2 Smith Street'.
Ok so my question is: how come BOTH markers don't show '2 Smith Street'?
In the past, I've looped through arrays of objects and bound event handlers to each object. In the event handler code itself, I would try to re-reference the corresponding object in the array, which is outside of the scope of the event handler. Thus, at the end of page load, the event handler for ALL objects referenced the LAST element in the loop. How come my sample geocode above didn't experience the same problem?
Forgive me if I'm not articulating the problem well. It is because very confused about the situation. I can't seem to 开发者_如何学Goget my head wrapped around variable scope with event handlers.....if someone can help me clarify, that would be great.
Additional Info/Confusion
Another thing...the variable var marker
was instantiated in the scope of geocodeCallBack()
. Isn't the marker destroyed by the time a user triggers google.maps.event.addListener(marker, 'click', function(){})
during run time? In which case, I should get some kind of undefined error?
{'address': address[rownum]}
is an object literal. Therefore, its value is determined at the exact time that the statement it is part of is executed, and future changes to address
or rownum
will not affects the object's address
member.
You are probably used to seeing this problem with closures (functions that reference variables from a parent scope). That is a different problem entirely, since the body of the function is usually not executed until some time later. Such a function continues to reference the same variables, not simply the same values.
But in this case, you are not creating any functions at all in your for
loop.
No, the marker
variable will still be alive -- that's part of what closures do. If you're from a C background, this will indeed seem mysterious. The outer function has returned; how could its locals continue to exist!?
The answer is that these variables get "closed around" by the anonymous function, and the runtime preserves their existence until the anonymous function is no longer referenced.
It didn't experience that problem because you are passing the value of address[rownum]
into the geocode
function at each iteration of the loop. You are not referencing rownum
after the loop is done, which would cause the problem that you're talking about.
Start your rownum index at zero.
for(var rownum=0; rownum < address.length; rownum++)
{
if(address[rownum])
geocoder.geocode( {'address': address[rownum]}, geocodeCallBack);
}
your loop variable looks incorrect btw.. shouldnt it be instantiated with 0 else you will only draw the marker at address[1]
精彩评论