16

Das ZielWie eine Variable nach Wert an eine anonyme Javascript-Funktion übergeben?

Ich möchte dynamisch an Event-Handler auf einige divs auf den Seiten während einer Website zugeordnet werden.

Meine Methode

Im jQuery mit anonymen Funktionen als Handler für ausgewählte div Ereignisse zu binden.

Das Problem

Der Code iteriert ein Array von div Namen und zugehörigen URLs. Der div-Name wird verwendet, um das Bindungsziel festzulegen, d. H. Diesen Ereignishandler an dieses div-Ereignis anzuhängen.

Während die Ereignishandler erfolgreich an jedes div-Ereignis gebunden sind, richten sich die von diesen Ereignishandlern ausgelösten Aktionen nur auf das letzte Element im Array.

Also die Idee ist, dass, wenn der Benutzer mouses über ein bestimmtes div, sollte es eine Slide-out-Animation für dieses div laufen. Stattdessen löst mousing over div1 (rangeTabAll) eine Slide-out-Animation für div4 (rangeTabThm) aus. Das gleiche gilt für divs 2, 3 usw. Die Reihenfolge ist unwichtig. Ändern Sie die Array-Elemente, und Ereignisse werden immer auf das letzte Element im Array, div4, ausgerichtet.

My-Code - (Verwendet 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);}); 
      } 
     } 

Meine Theorie

ich entweder keine blendend offensichtlich Syntaxfehler oder dessen einen Pass mit dem Bezugs Problem zu sehen. Anfangs hatte ich die folgende Anweisung den Wert von curTab einzustellen:

curTab=inlineRangeNavUrls[i][0]; 

Also, wenn das Problem aufgetreten ist ich dachte, dass, wie ich (über für Schleifeniterationslatenzzeit) geändert, um die Bezugnahme auf curTab, ich in der Tat Wechsel war die Referenz für alle früheren anonymen Funktionsereignishandler auch auf den neuen curTab-Wert ... weshalb Event-Handler immer das letzte div anvisierten.

Also, was ich wirklich brauchte, war zu tun, um den Wert auf das Ereignisse anonymen Funktion Handler curTab passiert nicht die curTab Objekt Referenz. So

ich dachte:

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

würde das Problem beheben, aber es funktioniert nicht. Gleicher Deal. Es fehlt also offensichtlich ein Schlüssel und wahrscheinlich sehr grundlegendes Wissen über das Problem. Vielen Dank.

+0

JavaScript wird immer übergeben und nach Wert zugewiesen. Deine Frage betrifft nicht das Übergehen überhaupt; sondern eher mit der Erfassung von Variablen durch Schließungen. – newacct

Antwort

20

tun :) Sie müssen bei jedem Durchlauf durch die Schleife eine neue Variable erstellen, so dass es in get gefangen werden die Schließungen, die Sie für die Ereignisbehandlungsroutinen erstellen.

Das Verschieben der Variablendeklaration in die Schleife wird dies jedoch nicht erreichen, da JavaScript doesn't introduce a new scope for arbitrary blocks.

Eine einfache Möglichkeit, die Einführung eines neuen Rahmen zu zwingen, ist eine andere anonyme Funktion zu verwenden:

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, Sie tatsächlich reinigen kann ziemlich viel mit jQuery eingebauten in hover() Funktion auf:

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

Tolles Zeug, danke. – rism

1

Ich denke, du machst das komplizierter, als es sein muss. Wenn Sie nur einen Schiebeeffekt bei mouseover/out zuweisen, versuchen Sie den Effekt hover mit jquery.

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

Wenn Sie Ihren vollständigen HTML geschrieben könnte ich Ihnen genau sagen, wie es

+2

stimmt, aber das ist nicht das, was das Problem verursacht. –

+0

... also bekomme ich einen Downvote? um eine einfachere und klarere Antwort auf das Problem des OP zu geben? Ja wirklich? – Jason

+0

Ihre Antwort löst das Problem des OP nicht. – Breton

15

was hier vor sich geht ist, dass Ihre anonmymous Funktionen eine Schließung bilden, und ihren äußeren Bereich mit ihnen nehmen. Das bedeutet, wenn Sie curTab innerhalb Ihrer anomymous Funktion referenzieren, wenn der Event-Handler diese Funktion ausführt, wird der aktuelle Wert von curTab in Ihrem äußeren Bereich nachgeschlagen. Das wird sein, was auch immer du curTab zugewiesen hast. (Nicht, was zu dem Zeitpunkt zugewiesen wurde binded Sie die Funktion)

was Sie brauchen, ist, dies zu tun ändern:

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

dazu:

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

dies den Wert von curTab kopiert in den Bereich der äußeren Funktion, die die innere Funktion mit sich bringt. Dieses Kopieren geschieht gleichzeitig mit der Bindung der inneren Funktion an den Event-Handler, so dass "mylocalvariable" den Wert von curTab zu diesem Zeitpunkt widerspiegelt. Beim nächsten Durchlauf der Schleife wird dann eine neue äußere Funktion mit einem neuen Bereich erstellt und der nächste Wert von curTab in sie kopiert.

Die Antwort von Shog9 erfüllt im Prinzip die gleiche Sache, aber sein Code ist etwas strenger.

es ist ein bisschen kompliziert, aber es macht Sinn, wenn Sie darüber nachdenken. Verschlüsse sind komisch.

edit: oops, vergessen, die innere Funktion zurückzugeben. Fest.

+0

Vielen Dank, ein bisschen Münze werfen für die angenommene Antwort. – rism

1

Sie können den Wert Ihrer Variablen in ein nicht vorhandenes Tag eingeben und später können Sie sie von dort lesen. Dieses Snippet ist Teil eines Schleifenkörpers:

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

um mit HTML5 kompatibel zu sein, können Sie 'data-' vor 'tag' hinzufügen, um' data-tag' zu erstellen, dann können Sie die jQuery ['data'] (http://api.jquery.com/data/) Methode verwenden. – Brombomb