OpenLayer中标记事件的奇怪行为

Day*_*mer 2 javascript events markers javascript-events openlayers

嘿.我的地图上有标记图层.

每次添加新标记时,我都会将其注册到鼠标单击事件:

var lonlat = new OpenLayers.LonLat(lon,lat);
var marker = new OpenLayers.Marker(lonlat,icon);
marker.id = callId;

marker.events.register("mousedown", marker, function() {AddPopup(marker.id);});

callMarkers.addMarker(marker);
Run Code Online (Sandbox Code Playgroud)

有时我想禁用/启用该事件.所以我使用这些功能:

function EnableAllMarkers()
{ 
    for (var i in callMarkers.markers)
    {
        callMarkers.markers[i].events.remove("mousedown");               

        callMarkers.markers[i].events.register("mousedown", callMarkers.markers[i],   

        function() { AddPopup(callMarkers.markers[i].id); });
    }  
}


function DisableAllMarkers()
{ 
    for (var i in callMarkers.markers)
    {
        callMarkers.markers[i].events.remove("mousedown");
    }  
}
Run Code Online (Sandbox Code Playgroud)

当我使用这段代码时,我会遇到奇怪的行为 - 有时会弹出错误标记的弹出窗口.我点击标记X并弹出Y打开.

有人可以帮帮我吗?

注意:EnableAllmMarkers首先删除事件的原因是因为我们不知道自添加新标记以来是否曾调用过DisableAllmMarkers.如果它确实被调用,删除函数将无能为力.

Poi*_*nty 7

这是一个经典的JavaScript陷阱:您在循环中将函数实例化为事件处理程序,并且函数引用局部变量.问题是它们引用了相同的局部变量:相同的,单一的,唯一的,只有一个位置的内存变量.在这种情况下,变量是"i".

在该for循环结束时,"i"将具有对象中最后一个键的值(顺便说一下,如果callMarkers.markers它实际上是一个数组,那么这不应该是一个for ... in循环,但这是一个单独的问题) .因此,当这些事件最终触发时,所有处理程序将使用"i"等于同一个键来执行它们的操作.

修理:

  for (var i in callMarkers.markers)
    {
        callMarkers.markers[i].events.remove("mousedown");               

        callMarkers.markers[i].events.register(
          "mousedown", 
          callMarkers.markers[i],
          (function(ii) {
            return function() {
              AddPopup(callMarkers.markers[ii].id);
            }
          )(i)
         );
    } 
Run Code Online (Sandbox Code Playgroud)

这引入了一个中间匿名函数.该函数立即被调用,并传递当前值"i".通过这样做 - 将"i"作为参数传递给匿名函数 - 该值在参数"ii"中被"捕获".每个循环迭代将导致另一个匿名函数的调用,它返回的函数(实际的处理程序)将有权访问它自己的私有"ii"变量.

还有其他一些方法可以实现同样的目标,但它们只是这个主题的变体.