You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Maps API JS:多选框生成标记时信息窗内容均为最后一项问题

问题原因分析

你遇到的这个问题是JavaScript闭包作用域导致的经典陷阱。在你的for循环里,用var location存储当前选项文本,但var声明的变量是函数级作用域的——当$.getJSON的异步回调执行时,整个循环已经跑完了,location变量最后会被更新为循环的最后一个值,所以所有标记的信息窗都会显示最后一项的内容。

解决方案

方法1:使用let代替var(ES6+推荐方案)

let声明的变量是块级作用域的,每次循环都会创建一个独立的location变量,回调函数会绑定当前循环迭代的那个值:

var locations = document.getElementById('waypoints');
for (let x = 0; x < locations.length; x++) { // x也改用let,保证每次循环的独立性
    let location = locations.options[x].text;
    window.alert(location);
    
    $.getJSON(
        'http://maps.googleapis.com/maps/api/geocode/json?address=' + location + '&sensor=false',
        null,
        function(data) {
            var p = data.results[0].geometry.location;
            var latlng = new google.maps.LatLng(p.lat, p.lng);
            var contentString = location; // 现在绑定的是当前循环的location值
            var infowindow = new google.maps.InfoWindow({
                content: contentString
            });
            var marker = new google.maps.Marker({
                position: latlng,
                animation: google.maps.Animation.DROP,
                map: map,
            });
            marker.addListener('click', function() {
                infowindow.open(map, marker);
            });
            gmarkers.push(marker);
        }
    );
}

方法2:用立即执行函数表达式(IIFE)创建闭包

如果需要兼容ES6之前的环境,可以用IIFE把每次循环的location值封装成独立作用域:

var locations = document.getElementById('waypoints');
var x;
for (x = 0; x < locations.length; x++) {
    var location = locations.options[x].text;
    window.alert(location);
    
    // 用IIFE保存当前循环的location值
    (function(currentLocation) {
        $.getJSON(
            'http://maps.googleapis.com/maps/api/geocode/json?address=' + currentLocation + '&sensor=false',
            null,
            function(data) {
                var p = data.results[0].geometry.location;
                var latlng = new google.maps.LatLng(p.lat, p.lng);
                var contentString = currentLocation; // 使用闭包保存的独立值
                var infowindow = new google.maps.InfoWindow({
                    content: contentString
                });
                var marker = new google.maps.Marker({
                    position: latlng,
                    animation: google.maps.Animation.DROP,
                    map: map,
                });
                marker.addListener('click', function() {
                    infowindow.open(map, marker);
                });
                gmarkers.push(marker);
            }
        );
    })(location); // 传入当前循环的location值
}

方法3:改用forEach循环

forEach的回调函数会为每个元素创建独立作用域,天然避免作用域共享问题:

var locations = document.getElementById('waypoints');
// 把options集合转换成数组后使用forEach
Array.from(locations.options).forEach(function(option) {
    var location = option.text;
    window.alert(location);
    
    $.getJSON(
        'http://maps.googleapis.com/maps/api/geocode/json?address=' + location + '&sensor=false',
        null,
        function(data) {
            var p = data.results[0].geometry.location;
            var latlng = new google.maps.LatLng(p.lat, p.lng);
            var contentString = location;
            var infowindow = new google.maps.InfoWindow({
                content: contentString
            });
            var marker = new google.maps.Marker({
                position: latlng,
                animation: google.maps.Animation.DROP,
                map: map,
            });
            marker.addListener('click', function() {
                infowindow.open(map, marker);
            });
            gmarkers.push(marker);
        }
    );
});
额外小提示

顺便提一句:你的Thymeleafselect标签里,th:field="${deliveries}"用于表单绑定的话,要确保后端接收的是对应option值的集合(也就是街道地址的集合),避免表单提交时出现数据不匹配的问题,不过这部分和当前JS问题无关,只是个小提醒~

内容的提问来源于stack exchange,提问作者Marios

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:15:56