为了在Google Map中创建标记的infowindows,我使用了一个数组在for循环中创建“一次性对象”。但是,我的方法似乎不起作用。单击标记不会执行任何操作,当我检查控制台时,我收到此错误消息:
Uncaught TypeError: Cannot call method 'open' of undefined
当我没有将对象分配给数组索引时,单击任何创建的标记只会打开最后一个信息窗口(意味着当对象被覆盖时,它会更新对前一个对象的所有引用)。
我该怎样绕过这个?
markers = []
infowindows = []
counter = 0
for location in exports.response.locations
myLatlng = new google.maps.LatLng(location.latitude, location.longitude);
markers[counter] = new google.maps.Marker(
position: myLatlng
map: map
title: location.name
)
contentString = '<div id="info_content_' + location.id + '">' + '<h3>' + location.name + '</h3>' + '<ul>' + '<li>' + location.address + ', ' + location.city + '</li>' + '</ul>'
infowindows[counter] = new google.maps.InfoWindow(content: contentString)
google.maps.event.addListener markers[counter], "click", ->
infowindows[counter].open(map, markers[counter])
counter++
注意
问题区域是上面代码中的第3行到最后一行。 (infowindows[counter].open(map, markers[counter])
)
答案
几乎每一个回答这个问题的人都帮我找到了解决办法,但是 - 为了记录(以及后来准备好的人)我用foreach解决了这个问题:
markers = []
infowindows = []
exports.response.locations.forEach (location) ->
myLatlng = new google.maps.LatLng(location.latitude, location.longitude);
markers[location.id] = new google.maps.Marker(
position: myLatlng
map: map
title: location.name
)
contentString = '<div id="info_content_' + location.id + '">' + '<h3>' + location.name + '</h3>' + '<ul>' + '<li>' + location.address + ', ' + location.city + '</li>' + '</ul>'
infowindows[location.id] = new google.maps.InfoWindow(content: contentString)
google.maps.event.addListener markers[location.id], "click", ->
infowindows[location.id].open(map, markers[location.id])
答案 0 :(得分:2)
我认为您的问题是counter
将不再具有有效索引:
for location in exports.response.locations
google.maps.event.addListener markers[counter], "click", ->
infowindows[counter].open(map, markers[counter])
counter++
在onClick处理程序闭包中捕获了 counter
。
在onClick处理程序运行之前,它将超出边界。
所有这些处理程序最终都会使用counter
的相同值。
答案 1 :(得分:1)
addListener异步触发代码。因此,当调用监听器的回调函数时,计数器的值与声明函数时的值不同。要将变量冻结为声明函数时的值,必须将它们放在闭包中。完整的证明选项如下。在循环中声明currentCounter应该足够了,但它可能有助于明确使用闭包。
markers = []
infowindows = []
counter = 0
for location in exports.response.locations
myLatlng = new google.maps.LatLng(location.latitude, location.longitude);
markers[counter] = new google.maps.Marker(
position: myLatlng
map: map
title: location.name
)
contentString = '<div id="info_content_' + location.id + '">' + '<h3>' + location.name + '</h3>' + '<ul>' + '<li>' + location.address + ', ' + location.city + '</li>' + '</ul>'
infowindows[counter] = new google.maps.InfoWindow(content: contentString)
google.maps.event.addListener markers[counter], "click", (function(infowindows, markers, currentcounter) {
return function() { infowindows[currentCounter].open(map, markers[currentCounter]) }
})(infowindows, markers, counter)
counter++
有关更多实际示例,请参阅JavaScript closure inside loops – simple practical example