Javascript - область видимости переменной в обработчике событий - PullRequest
2 голосов
/ 10 августа 2011

Может кто-нибудь прояснить мое понимание области видимости переменных в обработчиках событий?Взгляните на код ниже:

var address = new Array();
address[0] = '1 Smith Street';
address[1] = '2 Smith Street';

for(var rownum=0; rownum<=address.length; rownum++)
{
        if(address[rownum])
                geocoder.geocode( {'address': address[rownum]}, geocodeCallBack);
}


function geocodeCallBack(results, status)
{
        var marker = new google.maps.Marker({
            map: map,
            position: results[0].geometry.location,
            title: results[0].formatted_address
        });

        google.maps.event.addListener(marker, 'click', function(){
                var infowindow = new google.maps.InfoWindow({
                content: marker.title
                });
                // how come this event handler knows the marker variable references the marker variable declared about 10 lines above?
                infowindow.open(map, marker);
        });
}

Для большинства людей этот код кажется простым.Он наносит два маркера на карты Google.Когда вы нажимаете на первый маркер, он показывает адрес «1 Smith Street».Когда вы нажимаете на второй маркер, он показывает адрес «2 Smith Street».

Хорошо, поэтому мой вопрос: почему оба маркера не показывают «2 Smith Street» ?

В прошлом я перебирал массивы объектов и привязывал обработчики событий к каждому объекту.В самом коде обработчика событий я бы попытался повторно ссылаться на соответствующий объект в массиве, который находится за пределами области действия обработчика событий.Таким образом, в конце загрузки страницы обработчик событий для ВСЕХ объектов ссылался на элемент LAST в цикле.Почему мой пример геокода, описанный выше, не сталкивался с той же проблемой?

Простите, если я плохо сформулировал проблему.Это потому, что очень запутался в ситуации.Кажется, я не могу обернуть голову вокруг переменной области видимости обработчиками событий ..... если кто-то может помочь мне прояснить, это было бы здорово.

Дополнительная информация / Путаница Другоевещь ... переменная var marker была создана в области geocodeCallBack().Разве маркер не уничтожен к тому времени, когда пользователь запускает google.maps.event.addListener(marker, 'click', function(){}) во время выполнения?В каком случае я должен получить какую-то неопределенную ошибку?

Ответы [ 4 ]

3 голосов
/ 10 августа 2011

{'address': address[rownum]} является литералом объекта.Поэтому его значение определяется точно в то время, когда выполняется оператор, частью которого он является, и будущие изменения на address или rownum не повлияют на address член объекта.

Возможно, выимел обыкновение видеть эту проблему с замыканиями (функциями, которые ссылаются на переменные из родительской области).Это совсем другая проблема, поскольку тело функции обычно не выполняется до некоторого времени спустя.Такая функция продолжает ссылаться на те же переменные , а не просто на одни и те же значения.

Но в этом случае вы вообще не создаете никаких функций в цикле for.


Нет, переменная marker все еще будет работать - это часть того, что делают замыкания.Если вы из C-фона, это действительно покажется загадочным.Внешняя функция вернулась;как могут его локальные объекты продолжать существовать!?

Ответ заключается в том, что эти переменные «замыкаются» анонимной функцией, и среда выполнения сохраняет свое существование до тех пор, пока на анонимную функцию больше не будет ссылаться.

0 голосов
/ 10 августа 2011

ваша переменная цикла выглядит неправильно, кстати .. если она не будет создана с 0, иначе вы будете рисовать маркер только по адресу [1]

0 голосов
/ 10 августа 2011

Начните индекс rownum с нуля.

for(var rownum=0; rownum < address.length; rownum++)
{
        if(address[rownum])
                geocoder.geocode( {'address': address[rownum]}, geocodeCallBack);
}
0 голосов
/ 10 августа 2011

Эта проблема не возникла, потому что вы передаете значение address[rownum] в функцию geocode на каждой итерации цикла.Вы не ссылаетесь на rownum после завершения цикла, что может вызвать проблему, о которой вы говорите.

...