Селектор jQuery с использованием переменной в цикле массива - PullRequest
1 голос
/ 25 ноября 2011

У меня проблема с кодом ниже:

for (var i =0; i < filterArray.length; i++)
{

    name1 = filterArray[i];
    selectstring = 'a[cat="'+name1+'"]';
    filterMenuItem.addItem(name1 , function() {$(selectstring).show(); alert(selectstring)});


}

На данный момент filterArray содержит 2 элемента .. "Foo" и "Bar" ..

теперь этот "addItem (name1")работает нормально. Мы получаем добавленный пункт меню с именем Foo и другой с именем Bar

, проблема возникает со следующей частью (функцией).

и функции пунктов меню Foo & Bar заканчиваютсяделать то же самое (например, они оба получают строку выбора 'a [cat = "bar"]' ... как проверено с предупреждением)

Теперь я предполагаю, что это происходит, потому что переменная selectstringпередается по ссылке на функцию? Так, когда я устанавливаю значение selectstring во второй раз, оно переопределяет значение из первого цикла?

Как я могу передать уникальную копию selectstring в селектор?"function (selectstring) {....}", но это не помогло ..

Спасибо всем, кто может пролить свет на эту тему!

РЕДАКТИРОВАТЬ: Пересмотренный код ниже.Еще та же проблема:

for (var i =0; i < filterArray.length; i++)
{

    var name1 = filterArray[i];
    var selectstring = 'a[cat="'+name1+'"]';

    filterMenuItem.addItem(name1 , function() {alert(selectstring); $('.sortablelist').hide();  $(selectstring).show();});


}

Ответы [ 3 ]

1 голос
/ 25 ноября 2011

Это не имеет ничего общего с "передачей по ссылке" функции - фактически, функция ничего не передается.

Я думаю, что проблема в переменной области. Вы не использовали var до selectstring в строке назначения, поэтому предполагается, что это глобальная переменная. Анонимная функция сохранит ссылку на эту глобальную переменную, которая будет иметь значение 'bar' к моменту запуска функции. Если вы используете var selectstring = (...), на каждой итерации будет создаваться отдельное замыкание, и оно должно работать.

EDIT

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

for (var i=0; i < filterArray.length; i++) {
    addFilteredMenuItem(filterArray[i]);
}

function addFilteredMenuItem(itemName) {
    var selectstring = 'a[cat="'+itemName+'"]';
    filterMenuItem.addItem(itemName, function() {
       alert(selectstring);
    });
}

Рабочий пример для jsfiddle

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

См. Также в этой теме , обсуждающей ту же тему.

1 голос
/ 25 ноября 2011

Ваш цикл for имеет только одно замыкание, поэтому всегда будет использоваться «последнее» значение selectstring. Вам нужно начать новое закрытие, как показано ниже:

for (var i =0; i < filterArray.length; i++)
{
  name1 = filterArray[i];
  selectstring = 'a[cat="'+name1+'"]';
  filterMenuItem.addItem(name1, 
    (
     function(selectstring) 
     { 
       return function() {$(selectstring).show(); alert(selectstring) }
     }
    )(selectstring)
  );
}

Функция вызывается немедленно, пока правильное значение selectstring все еще там, и внешняя функция создает новое закрытие (и, следовательно, новую копию ее локальных переменных) для возвращенной внутренней функции.

Функция jQuery .each () также может быть немного проще в вашем случае:

$.each(this.filterArray, function(i, filter) {
    filterMenuItem.addItem(name1 , function() {$('a[cat="'+filter+'"]').show(); alert('a[cat="'+filter+'"]')});
});
0 голосов
/ 25 ноября 2011

Я не знаю, знаю ли я, что Вам нужно, но попробуйте:

for (var i =0; i < filterArray.length; i++)
{

    name1 = filterArray[i];
    selectstring = 'a[cat="'+name1+'"]';
    filterMenuItem.addItem(name1 , function(selectstring) {$(selectstring).show(); alert(selectstring)});

}
...