为什么循环控制变量没有在当前值处传递给回调函数

Why are loop control variable not passed at the current value to callback functions?

本文关键字:函数 回调 控制变量 循环 为什么      更新时间:2023-09-26

我正在尝试使用谷歌地图API构建地图,该API以JSON格式加载数据并将点添加到地图中。

以下是 html 页面,可在 servername.com/kmltest/mapsapi.html 访问:

<!DOCTYPE html>
<html>
  <head>
    <title>Google Maps javascript</title>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <style>
      html, body, #map-canvas {
        height: 100%;
        margin: 0px;
        padding: 0px
      }
    </style>
    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
    <script>
function drawAllPoints()
    {pointsData.numLayers = pointsData.layers.length;
        for (var i = 0; i < pointsData.numLayers; i++)
            {var numPoints = pointsData.layers[i].points.length;
            pointsData.layers[i].visible = true;
            document.getElementById("layerSidebarInner").innerHTML = document.getElementById("layerSidebarInner").innerHTML + "<input type='"checkbox'" id='"" + pointsData.layers[i].name + "'" >" + pointsData.layers[i].name + "<br />";
            //Eventually, make the checkbox trigger showing and hiding
            //pointsData.layers[i].layerColor = ; //Change a point color variable for this layer?
            for (var j = 0; j < numPoints; j++)
                {// Create a Lat/Long object.
                window.pointsData.layers[i].points[j].position = new google.maps.LatLng(window.pointsData.layers[i].points[j].lat, window.pointsData.layers[i].points[j].long);
                // Set up each point
                window.pointsData.layers[i].points[j].marker = new google.maps.Marker({
                    position: window.pointsData.layers[i].points[j].position,
                    map: window.map,
                    title : window.pointsData.layers[i].points[j].username
                });
                // Set up each information window
                infoWindow = new google.maps.InfoWindow({
                    position: window.pointsData.layers[i].points[j].position,
                    map: window.map,
                    title: window.pointsData.layers[i].points[j].username,
                    content: 'Test '+i+", "+j
                });
                // Try to add a handler that shows the balloon. Why does it show "2 2" and not the array indexes?
                google.maps.event.addListener(pointsData.layers[i].points[j].marker, 'click', function() {alert(i+" "+j);});
                }
        }
    }

var map;
var marker;
var myLatlng;
function initialize() {
myLatlng = new google.maps.LatLng(44.759705, -117.823371);
var mapOptions = {
zoom: 17,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.HYBRID
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

// This used to be it's own function. Fires off a HTTP request for the Json customer data
var pointsDataJsonhttp;
// code for IE7+, Firefox, Chrome, Opera, Safari, I really don't care about IE6 and 5
pointsDataJsonhttp=new XMLHttpRequest();
pointsDataJsonhttp.onreadystatechange=function()
{
if (pointsDataJsonhttp.readyState==4 && pointsDataJsonhttp.status==200)
    {
    window.pointsData = eval("(" + pointsDataJsonhttp.responseText + ")");
    drawAllPoints();
    }
}
pointsDataJsonhttp.open("GET","/kmltest/test.json",true);
pointsDataJsonhttp.send();
}
//I can't seem to make this work yet, but I'm not worrying about it right now
/*function toggleLayer(layernumber)
{
    if (pointsData.layers[layernumber].visible) {
        pointsData.layers[layernumber] = false;
        }
    else {pointsData.layers[layernumber].visible = true;}
    numPoints = pointsData.layers[layernumber].points.length
    for (j=0; j < numPoints; j++)
        {
        pointsData.layers[layernumber].points[j].setVisible(pointsData.layers[layernumber].visible);
        }
}*/
// Seems like these two do the same thing, so I'm only using one of them
google.maps.event.addDomListener(window, 'load', initialize);
//window.onload = initialize;
    </script>
  </head>
  <body>
    <div id="layerSidebar" style="width: 20%; float: left;"><div id="layerSidebarInner" style="margin:10px;"></div></div>
    <div id="map-canvas" style="width: 80%; float: left;"></div>
    <!-- This line makes any following content get below the bottom of the 2 columns above -->
    <div style="clear: both"></div>
  </body>
</html>

下面是它正在加载的(当前静态)JSON,可在服务器上 servername.com/kmltest/test.json

{ "layers" :
    [
        {"name" : "Shelf18", 
        "broadband": "adsl",
        "type" : "customerlist",
        "points" :
            [ {"username" : "thompsondsl", "long" : -117.823711, "lat" : 44.760645, "shelf" : "18", "slot": "3", "port" : "2"},
            {"username": "johnsondsl", "long" : -117.822471, "lat" : 44.759705, "shelf": "18", "slot": "3", "port" : "3"}
            ]
        },
        {"name" : "Shelf17",
        "broadband": "adsl",
        "type" : "customerlist",
        "points" :
            [ {"username" : "andersendsl17", "long" : -117.823811, "lat" : 44.760645, "shelf" : "18", "slot": "4", "port" : "2"},
            {"username": "smithdsl", "long" : -117.823371, "lat" : 44.759705, "shelf": "18", "slot": "11", "port" : "3"}
            ]
        }
    ]
}

正如您可能看到的,我已经放置了一些警报框来尝试帮助调试。我不明白为什么当我单击地标时,它总是给出"2 2"的结果,而不是"0 1"之类的结果,具体取决于我单击的地标。就好像它得到了循环控制变量最终得到的值吗?如果这就是快乐,我如何正确地做到这一点,以免发生这种情况?

尝试将

代码包装在函数中。这将创建一个包含ij的本地副本的私有上下文:

(function (i, j) {
    var marker = pointsData.layers[i].points[j].marker;
    google.maps.event.addListener(marker, 'click', function() { 
        alert(i + " " + j); 
    });
})(i, j);

你也可以这样做:

var marker = pointsData.layers[i].points[j].marker;
google.maps.event.addListener(marker, 'click', function() { 
    return function() { alert(i + " " + j); };
}(i, j));