Javascript命名空间和范围:需要澄清

时间:2014-03-07 01:41:03

标签: javascript namespaces scope

请查看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,这是因为标记被循环中的新标记覆盖。但是,我不明白事件监听器如何正确关联正确的标记,而只有在单击时打开与最后一个标记关联的信息窗口。有人可以详细说明这里到底发生了什么吗?

2 个答案:

答案 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);
                                                  };
                                                }()));