Подтвердить что ты не робот

Как передать переменную по значению анонимной функции javascript?

Цель

Я хочу динамически назначать обработчики событий некоторым div на страницах по всему сайту.

Мой метод

Im использует jQuery для привязки анонимных функций как обработчиков для выбранных событий div.

Проблема

Итерирует массив имен div и связанных URL. Имя div используется для установки целевого объекта привязки, т.е. присоединяет этот обработчик события к этому событию div.

В то время как обработчики событий успешно связаны с каждым из Див событий, действия, спровоцированные этими обработчики событий только когда-либо целевой последний элемент в массиве.

Итак, идея состоит в том, что если пользователь переводит мышью по данному div, он должен запустить анимацию скольжения для этого div. Но вместо этого mousing над div1 (rangeTabAll) запускает анимацию скольжения для div4 (rangeTabThm). То же самое верно для divs 2, 3 и т.д. Порядок неважен. Измените элементы массива вокруг, и события всегда будут нацелены на последний элемент в массиве div4.

Мой код - (использует jQuery)

var curTab, curDiv;
var inlineRangeNavUrls=[['rangeTabAll','range_all.html'],['rangeTabRem','range_remedial.html'],
                ['rangeTabGym','range_gym.html'],['rangeTabThm','range_thermal.html']];
        for (var i=0;i<inlineRangeNavUrls.length;i++)
        {
            curTab=(inlineRangeNavUrls[i][0]).toString();
            curDiv='#' + curTab;
            if  ($(curDiv).length)
            {
                $(curDiv).bind("mouseover", function(){showHideRangeSlidingTabs(curTab, true);} );
                $(curDiv).bind("mouseout", function(){showHideRangeSlidingTabs(curTab, false);} );
            }
        }

Моя теория

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

curTab=inlineRangeNavUrls[i][0];

Итак, когда возникла проблема я понял, что, как я изменил (через для итерации цикла) ссылки на curTab, я был на самом деле изменением ссылки для всех предыдущих обработчиков событий анонимной функции к новому значению curTab а.... поэтому обработчики событий всегда нацелены на последний div.

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

Итак, я подумал:

curTab=(inlineRangeNavUrls[i][0]).toString();

устранит проблему, но это не так. Такая же сделка. Таким образом, очевидно, что я пропустил некоторые ключевые и, возможно, очень простые знания о проблеме. Спасибо.

4b9b3361

Ответ 1

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

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

Одним из простых способов заставить введение новой области является использование другой анонимной функции:

for (var i=0;i<inlineRangeNavUrls.length;i++)
{
  curDiv='#' + inlineRangeNavUrls[i][1];
  if ($(curDiv).length)
  {
    (function(curTab)
    {
      $(curDiv).bind("mouseover", function(){showHideRangeSlidingTabs(curTab, true);} );
      $(curDiv).bind("mouseout", function(){showHideRangeSlidingTabs(curTab, false);} );
    })(inlineRangeNavUrls[i][0]); // pass as argument to anonymous function - this will introduce a new scope
  }
}

Как предлагает Джейсон, вы можете немного почистить это, используя встроенный jQuery hover():

for (var i=0;i<inlineRangeNavUrls.length;i++)
{
  (function(curTab) // introduce a new scope
  {
  $('#' + inlineRangeNavUrls[i][1])
    .hover(
      function(){showHideRangeSlidingTabs(curTab, true);},
      function(){showHideRangeSlidingTabs(curTab, false);} 
    );
  // establish per-loop variable by passsing as argument to anonymous function
  })(inlineRangeNavUrls[i][0]); 
}

Ответ 2

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

что вам нужно сделать, это изменить это:

$(curDiv).bind("mouseover", function(){showHideRangeSlidingTabs(curTab, true);} );

:

$(curDiv).bind("mouseover", 
    (function (mylocalvariable) { 
        return function(){
            showHideRangeSlidingTabs(mylocalvariable, true);
        } 
    })(curTab) 
);

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

shog9 answer выполняет в основном одно и то же, но его код немного более строгий.

это довольно сложно, но это имеет смысл, если вы думаете об этом. Закрытия странные.

edit: oops, забыл вернуть внутреннюю функцию. Фиксированный.

Ответ 3

Я думаю, что вы делаете это более сложным, чем это должно быть. Если все, что вы делаете, назначает скользящий эффект на mouseover/out, попробуйте hover эффект с jquery.

$("#mytab").hover(function(){
    $(this).next("div").slideDown("fast");},
  function(){
    $(this).next("div").slideUp("fast");
});

Если вы разместили свой полный HTML-код, я могу точно сказать, как это сделать:)

Ответ 4

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

 s = introduction.introductions[page * 6 + i][0]; //The variables content
 $('#intro_img_'+i).attr('tag' , s);              //Store them in a tag named tag
 $('#intro_img_'+i).click( function() {introduction.selectTemplate(this, $(this).attr('tag'));}  );  //retrieve the stored data