请查看Google Maps API中的以下两个代码示例:
为:
for (var i = 0; i < 8; i++) {
var marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(lat[i], lng[i]),
icon: '/static/images/iconsets/gmap/iconb' + (i+1) + '.png',
});
var infowindow = new google.maps.InfoWindow({
content: 'test string'
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
}
不可
for (var i = 0; i < 8; i++) {
createMarker(i);
}
function createMarker(i) {
var marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(lat, lng),
icon: '/static/images/iconsets/gmap/iconb' + (i+1) + '.png',
});
var infowindow = new google.maps.InfoWindow({
content: 'test string'
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
}
第一个代码示例的问题是,当单击任何marker
时,事件处理程序将打开与 last 标记关联的infowindow,而不是单击的标记。根据这个post,这是因为标记被循环中的新标记覆盖。但是,我不明白事件监听器如何正确关联正确的标记,而只有在单击时打开与最后一个标记关联的信息窗口。有人可以详细说明这里到底发生了什么吗?
答案 0 :(得分:2)
每个范围都可以有一个,只能绑定一个特定的名称。您可以将其视为可变对象。事件侦听器具有对此对象的引用,因此当您在循环中更改它时,所有引用都会更改。
哦,在JS中创建范围(或者如果你愿意的话)的唯一方法是使用function()
答案 1 :(得分:2)
在第一个代码示例中:
for (var i = 0; i < 8; i++) {
var marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(lat[i], lng[i]),
icon: '/static/images/iconsets/gmap/iconb' + (i+1) + '.png',
});
javascript中没有块范围,因此上述内容相当于:
var marker, infowindow;
for (var i = 0; i < 8; i++) {
marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(lat[i], lng[i]),
icon: '/static/images/iconsets/gmap/iconb' + (i+1) + '.png',
});
因此,在每个循环中,新的 google.mapsMarker 被分配给标记。 infowindow 也是如此。然后当你这样做:
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
分配给侦听器的所有函数都关闭一个 infowindow 实例, map 和标记,因此当调用任何侦听器时,它们都引用分配给这些变量的最后一个值。
在第二种情况下,将值传递给anther函数来执行赋值会中断闭包(因为它是传递的值,而不是变量),因此您在调用时获取值createMarker 功能。您还可以将第一个示例与立即调用的函数表达式(IIFE)一起使用:
google.maps.event.addListener(marker, 'click', (function() {
return function() {
infowindow.open(map,marker);
};
}()));