Доступ к итерации цикла в подфункции? - PullRequest
2 голосов
/ 19 января 2010

Я использую API Карт Google, чтобы нанести несколько точек на карту. Однако в приведенной ниже функции события щелчка значение i всегда равно 4, то есть его значение после повторения цикла:

// note these are actual addresses in the real page
var addresses = new Array( "addr 1", "addr 2", "addr 3", "addr 4" );

for (var i = 0; i < addresses.length; i++) {
    geocoder.getLatLng(addresses[i], function(point) {
        if (point) {
            var marker = new GMarker(point);
            map.addOverlay(marker);
            map.setCenter(point, 13);

            GEvent.addListener(marker, "click", function() {
                // here, i=4
                marker.openInfoWindowHtml("Address: <b>" + addresses[i] + "</b>");
            });
        }
    });
}

Поэтому, когда маркер отображает, он использует addresses[4], который не определен. Как передать правильное значение i в функцию?

Ответы [ 2 ]

1 голос
/ 19 января 2010

Вам необходимо сгенерировать анонимную функцию во время текущей итерации, следующее должно это исправить:

// note these are actual addresses in the real page 
var addresses = new Array( "addr 1", "addr 2", "addr 3", "addr 4" ); 

for (var i = 0; i < addresses.length; i++) { 
    geocoder.getLatLng(addresses[i], function (current) { 
        return function(point) { 
            if (point) { 
                var marker = new GMarker(point); 
                map.addOverlay(marker); 
                map.setCenter(point, 13); 

                GEvent.addListener(marker, "click", function() { 
                    // here, i=4 
                    marker.openInfoWindowHtml("Address: <b>" + addresses[current] + "</b>"); 
                }); 
            }
        } 
    }(i)); 
} 

B // обратите внимание, что это реальные адреса в реальной странице var address = new Array ("addr1 "," адрес 2 "," адрес 3 "," адрес 4 ");

для (var i = 0; i

GEvent.addListener(marker, "click", function() { // here, i=4 marker.openInfoWindowHtml("Address: <b>" + addresses[i] + "</b>"); }); } });

}

Дальнейшее уточнение
Метод getLatLng, предоставленныйGoogle использует вызов ajax для получения широты и долготы для определенного адреса. Поскольку это асинхронный вызов, который не является частью текущего потока, требуется функция обратного вызова, которая вызывается при завершении запроса ajax. Это анонимный вызов.Функция, которую вы указываете в качестве второго параметра функции.
Теперь, пока выполняются запросы Ajax, ваш код продолжает выполняться, увеличивая значение i каждый раз, когда цикл выполняет итерации по массиву.Когда возвращается первый вызов ajax, цикл уже увеличился до длины массива адресов (4), поэтому, когда ваша функция обратного вызова запускается, вы извлекаете переменную в области действия i после того, как она былаувеличено в цикле.

С помощью написанного мною исправления вы создаете анонимную функцию, которая принимает один аргумент - current - и возвращает предыдущую анонимную функцию с заменой переменной i на переменную current.Эта функция вызывается сразу, до следующей итерации цикла, с переменной i в качестве первого параметра.Это создает замыкание, для которого текущее значение i сохраняется в переменной current во время вызова функции.Когда мы ссылаемся на переменную current позже, мы получаем сохраненное значение i.

Я не очень хорош в объяснении такого рода вещей, вероятно, потому что мое понимание этого нене так хорошо, как JS богов.Лучше прочитать немного больше информации о закрытиях JavaScript .

0 голосов
/ 19 января 2010

я не должен достигать 4 в этом цикле. Цикл выполняется до тех пор, пока i

...