我正在扩展我的previous question,因为我仍然不完全理解javascript闭包的概念。快速查看以下代码,它将在地图上放置两个标记。 (代码稍微修改了我之前的问题)。
var map = google.maps.somefunctoinstantiatemap();
var address = new Array();
address[0] = '1 Smith Street';
address[1] = '2 Smith Street';
function onpageload()
{
for(var rownum=0; rownum<address.length; rownum++)
{
geocoder.geocode({
'address': address[rownum]
}, function(results, status) {
geocodeCallBack(results,status,rownum)
});
}
}
function geocodeCallBack(results, status, argnum)
{
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
title: 'arg: '+argnum+' addr:'+results[0].formatted_address
});
google.maps.event.addListener(marker, 'click', function(){
var infowindow = new google.maps.InfoWindow({
content: marker.title
});
infowindow.open(map, marker);
});
}
好的,多项选择....用户点击两个标记时的结果是什么?
当我运行代码时,答案是3.但我希望答案是4或5.为什么不是4,为什么不是5?
答案 0 :(得分:4)
你似乎期望闭包关闭某些东西(它确实如此),但是你没有特别使用它在它中关闭的东西(比如循环索引)。 argnum
中的geocodeCallBack
值来自Google(因为您已将rownum
定义为匿名函数的第三个参数,shadowing循环计数器),它是与你的循环计数器无关。
关于该代码的其他几点:
您在顶部的循环循环三次次,而不是两次。您可以从 (你已经修好了。) 0
转到<= results.length
。 results.length
为2
,因此会以rownum
值0
,1
和2
为循环。你的意思是< results.length
。
这里的匿名功能没有用处:
geocoder.geocode( {'address': address[rownum]}, function(results, status, rownum) {geocodeCallBack(results,status,rownum)});
...因为它所做的就是传递它收到的参数。这可能也许应该只是:
geocoder.geocode( {'address': address[rownum]}, geocodeCallBack);
...除非函数的签名是错误的,否则你不应该声明所有这些参数。
修改:根据您的评论,我认为您可能需要这样:
geocoder.geocode( {'address': address[rownum]}, makeCallback(rownum));
function makeCallback(therow) {
return function(results, status) {
geocodeCallBack(results, status, therow);
};
}
...或者在您输入的“真实代码”中,您实际上将该行号用作选择器的一部分:
geocoder.geocode( {'address': address[rownum]}, makeCallback(rownum));
function makeCallback(therow) {
return function(results, status) {
geocodeCallBack(results, status, $('#row-' + therow).val());
};
}
makeCallback
函数创建一个函数作为回调。它创建的函数关闭传递给therow
的{{1}}参数,该参数永远不会更改,因此您为第一个循环创建的回调获得makeCallback
therow
,并且0
为therow
,表示您在第二个循环中创建的回调。
在理解闭包方面,我写了这篇文章,我认为你可能会觉得有用:Closures are not complicated它介绍了闭包如何工作的机制。标题不是谎言:他们不复杂,人们倾向于把自己捆绑在一起,因为他们认为他们很复杂,但他们不是。 / p>
答案 1 :(得分:0)
geocode()会覆盖numrow的值。
for(var rownum=0; rownum<=address.length; rownum++)
{
geocoder.geocode( {'address': address[rownum]}, function(results, status) {geocodeCallBack(results,status,rownum)});
}
尝试这样做,这样geocodeCallBack就会被发送到forloop中声明的rownum
结果应该是第一个标记显示'arg:0 addr:1 Smith Street',第二个标记显示'arg:1 addr:2 Smith Street'