16

CelemJak przekazać zmienną po wartości do anonimowej funkcji javascript?

Chcę dynamicznie przypisać obsługi zdarzeń do niektórych DIV na stronach w całej witrynie.

moja metoda

Im jQuery związać anonimowych funkcje jak ładowarki do wybranych zdarzeń DIV.

Problem

Kod iteracje tablicę dz opisów i powiązanych adresów URL. Nazwa div służy do ustawienia celu wiązania, tj. Dołączenia tej procedury obsługi zdarzeń do tego zdarzenia div.

Chociaż programy obsługi zdarzeń są z powodzeniem powiązane z każdym z zdarzeń div, akcje wywoływane przez te procedury obsługi zdarzeń są kierowane tylko na ostatni element w tablicy.

Chodzi o to, że jeśli użytkownik myszkuje nad danym elementem div, powinien uruchomić animację wysuwaną dla tego elementu div. Zamiast tego, mousing nad div1 (rangeTabAll) wyzwala wysunięcie animacji dla div4 (rangeTabThm). To samo dotyczy div 2, 3 itd. Kolejność nie ma znaczenia. Zmień elementy tablicy, a zdarzenia będą zawsze kierowane na ostatni element tablicy div4.

mojego kodu - (Używa 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);}); 
      } 
     } 

moja teoria

Ja też nie widząc oślepiająco oczywisty błąd składni lub jej przepustkę od problemu odniesienia. Początkowo miałem następującą instrukcję, aby ustawić wartość curTab:

curTab=inlineRangeNavUrls[i][0]; 

Więc kiedy problem wystąpił Pomyślałem, że jak już zmienić (za pośrednictwem pętli iteracji) odniesienie do curTab, byłem w rzeczywistości zmieniając odwołanie do wszystkich poprzednich funkcji obsługi zdarzeń anonimowych funkcji do nowej wartości curTab, a także .... dlatego procedury obsługi zdarzeń zawsze były kierowane na ostatni element div.

Więc co tak naprawdę potrzebne do zrobienia było przekazać wartość curTab do anonimowych funkcja obsługi zdarzeń nie curTab obiekt odniesienia.

więc pomyślałem:

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

by rozwiązać ten problem, ale tak nie jest. Taki sam układ. Tak więc wyraźnie brakuje im kluczowej i prawdopodobnie bardzo podstawowej wiedzy na temat problemu. Dzięki.

+0

JavaScript zawsze przekazuje i przypisuje wartość. Twoje pytanie w ogóle nie dotyczy przekazywania; ale raczej przechwytywanie zmiennych przez zamknięcie. – newacct

Odpowiedz

20

Musisz utworzyć nową zmienną na każdym przejściu przez pętlę, tak że będzie ona dostać ujęte w zamknięcia, które tworzysz dla procedur obsługi zdarzeń.

Jednak przeniesienie deklaracji zmiennej do pętli nie spowoduje tego, ponieważ JavaScript doesn't introduce a new scope for arbitrary blocks.

Prostym sposobem, aby wymusić wprowadzenie nowego zakresu jest użycie innego anonimową funkcję:

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 
    } 
} 

As Jason suggests, rzeczywiście można to posprzątać trochę jQuery wbudowanej hover() funkcji:

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]); 
} 
+0

Świetne rzeczy, dzięki. – rism

1

Myślę, że robisz to bardziej skomplikowanym, niż powinno być. Jeśli wszystko, co robisz, przypisuje efekt przesuwania przy najechaniu myszą/na zewnątrz, spróbuj użyć efektu jquery za pomocą efektu hover.

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

Jeśli pisał swój pełny kod HTML mogę powiedzieć dokładnie, jak to zrobić :)

+2

prawda, ale to nie jest przyczyną problemu. –

+0

... więc dostałem awans? za udzielenie prostszej, jaśniejszej odpowiedzi na problem PO? naprawdę? – Jason

+0

Twoja odpowiedź nie rozwiązuje problemu PO. – Breton

15

To, co się tutaj dzieje, to to, że twoje funkcje anonimiczne tworzą zamknięcie i zabierają ze sobą ich zewnętrzny zakres. Oznacza to, że gdy odwołujesz się do curTab w swojej anormalnej funkcji, kiedy funkcja obsługi zdarzeń uruchamia tę funkcję, to wyszuka wartość curTab w twoim zewnętrznym zasięgu. To będzie wszystko, co ostatnio przypisałeś do curTab. (Nie to, co zostało przypisane w momencie zbindowanych funkcję)

co trzeba zrobić, to zmienić:

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

do tego:

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

to skopiuje wartość curTab w zakresie funkcji zewnętrznej, którą funkcja wewnętrzna weźmie ze sobą. To kopiowanie dzieje się w tym samym czasie, kiedy łączysz wewnętrzną funkcję z obsługą zdarzeń, więc "mylocalvariable" odzwierciedla wartość curTab w tym czasie. Następnie następnym razem wokół pętli zostanie utworzona nowa funkcja zewnętrzna, z nowym zakresem, a następnie skopiowana do następnej wartości curTab.

Odpowiedź shog9 spełnia w zasadzie to samo, ale jego kod jest trochę bardziej surowy.

To trochę skomplikowane, ale ma sens, jeśli o tym pomyślisz. Zamknięcia są dziwne.

edytuj: oops, zapomniałem zwrócić funkcję wewnętrzną. Naprawiony.

+0

Wielkie dzięki, trochę rzutu monetą za zaakceptowaną odpowiedź. – rism

1

Możesz wstawić wartość zmiennej do nieistniejącego znacznika, a później możesz je odczytać stamtąd. Ten fragment jest częścią treści pętli:

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 
+0

aby być kompatybilnym z HTML5 możesz dodać 'data-' przed 'tag', aby utworzyć' dane-znacznik', a następnie możesz użyć metody jQuery ['data'] (http://api.jquery.com/data/). – Brombomb

Powiązane problemy