Как я могу работать с замыканиями Javascript? - PullRequest
6 голосов
/ 06 июня 2011

Рассмотрим этот небольшой фрагмент JavaScript:

for(var i in map.maps)
{
    buttons.push($("<button>").html(i).click(function() { alert(i); }));
}

Создает одну кнопку для каждого из полей в объекте map.maps (это массив ассоциаций). Я установил указатель в качестве текста кнопки и настроил его также на оповещение. Очевидно, можно ожидать, что все кнопки будут предупреждать свой собственный текст при нажатии, но вместо этого все кнопки будут предупреждать текст окончательного индекса в объекте map.maps при нажатии.

Полагаю, такое поведение вызвано изящным образом JavaScript обрабатывает замыкания, возвращаясь и выполняя функции из замыканий, в которых они были созданы.

Единственный способ обойти это - установить индекс в качестве данных для объекта кнопки и использовать его из обратного вызова click. Я также мог бы имитировать индексы map.maps в моем объекте buttons и находить правильный индекс при нажатии, используя indexOf, но я предпочитаю первый метод.

То, что я ищу в ответах, это подтверждение того, что я делаю это правильно, или предложение о том, как я должен сделать это.

Ответы [ 4 ]

9 голосов
/ 06 июня 2011

Охватите замыкания, не обходите их.

for(var i in map.maps)
{
    (function(i){
        buttons.push($("<button>").html(i).click(function() { alert(i); }));
    })(i);
}

Вам нужно обернуть код, который использует ваш var i, чтобы он заканчивался отдельным замыканием, а значение сохранялось вlocal var / param для этого замыкания.

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

4 голосов
/ 06 июня 2011

Если вы передадите измененное значение другой функции в качестве параметра, значение будет заблокировано в:

function createButton(name) {
    return $("<button>").html(name).click(function() { alert(name); });
}

for (var i in map.maps) {
    buttons.push(createButton(i));
}
1 голос
/ 06 июня 2011
for(var i in map.maps){
    (function(i){
         buttons.push($("<button>").html(i).click(function() { alert(i); }))
    })(i);
}

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

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

0 голосов
/ 06 июня 2011

Это самый элегантный способ сделать то, что вы пытаетесь сделать:

var buttons = myCharts.map(function(chart,i) {
    return $("<button>").html(chart).click(function(event){
        alert(chart);
    });
}

Вам нужно замыканий, чтобы элегантно кодировать в javascript, и не должны обходить их,Или же вы не можете делать такие вещи, как вложенные в циклы (без ужасных взломов).Когда вам нужно закрытие, используйте закрытие.Не бойтесь определять новые функции внутри функций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...