remove-event-problem, wenn handler-fkt innere fkt ist
return maybe;
- javascript
0 dave0 return maybe;0 return maybe;0 ChrisB
0 molily
Guten Abend!
Nach ewig langer Fehlersuche hab ich mein Problem jetzt stark eingrenzen können,
aber irgendwie hab ich das Gefühl, etwas ganz Grundlegendes zu übersehen...
Hier das extrem vereinfachte Szenario:
bla = {
handle : function ( elem, remove ) {
if ( remove ) {
elem.removeEventListener( 'mousedown', down, true );
return this;
}
elem.addEventListener( 'mousedown', down, true );
function down(e) { /* action on mousedown */ }
return this;
}
}
Für ein Element einen Listener mit bla.handle( el ) zu registrieren, klappt;
wenn ich dagegen mit bla.handle( el, true ) den selbigen wieder abmelden will,
geht etwas schief.
Das muss damit zutun haben, dass der handler ( die Funktion down ) eine private
Funktion von bla.handle ist.
Es würd hier zu weit führen, zu erklären, warum ich letzteres so haben möchte.
Kann mir einer die Bäume absägen, damit ich den Wald wieder seh?
Vielen lieben Dank!
Hi,
beim zweiten Aufruf von handle wird eine neue function down erzeugt.
Das ist nicht mehr die selbe wie die vorher zugewiesene, und kann daher auch nicht entfernt werden.
Zum Verständnis evtl einfach mal folgendes ausführen:
var foo = function(){return 1+1;},
bar = function(){return 1+1;},
baz = foo;
alert(foo === bar);
alert(foo === baz);
Ersteres gibt false aus, da die Funktionen zwar genau das gleiche tun, aber eben nicht die selbe Funktion _sind_.
Zweiteres hingegen true, da es zwar Variablen unterschiedlichen Namens sind, beide aber die gleiche function referenzieren.
Wie genau du das am geschicktesten löst kann ich so ganz ohne Zusammenhang schlecht sagen.
~dave
Hallo Dave,
beim zweiten Aufruf von handle wird eine neue function down erzeugt.
vielen Dank :)
Wie genau du das am geschicktesten löst kann ich so ganz ohne Zusammenhang schlecht sagen.
da wird sich schon was finden, wär ja gelacht^^
schönen Abend Dir noch
Nachtrag:
Wie genau du das am geschicktesten löst kann ich so ganz ohne Zusammenhang schlecht sagen.
Eine Option gefunden (vielleicht find ich noch 'ne bessere...):
wenn ich die erste Funktion down in z.B. bla.oldDown abspeicher ( bla.oldDown = down), dann klappt das Abmelden via elem.removeEventListener('mousedown',bla.oldDown,true)
:)
Hi,
beim zweiten Aufruf von handle wird eine neue function down erzeugt.
Das ist nicht mehr die selbe wie die vorher zugewiesene, und kann daher auch nicht entfernt werden. [...]
Wie genau du das am geschicktesten löst kann ich so ganz ohne Zusammenhang schlecht sagen.
Die Funktionen einfach nicht verschachteln, sondern down einfach auf der gleichen "Ebene" wie handle als Unter-Objekt von bla.
MfG ChrisB
Hallo,
Das muss damit zutun haben, dass der handler ( die Funktion down ) eine private
Funktion von bla.handle ist.
Es würd hier zu weit führen, zu erklären, warum ich letzteres so haben möchte.
Erkläre es trotzdem mal, denn das ist die Ursache des Problems.
Es gibt keine »private Funktionen« in JavaScript. (Siehe OOP in JavaScript.) Privatheit gibt es nur durch Funktions-Scopes. Du definierst hier die Funktion, dessen Zugriff du gleichzeitig ermöglichen und beschränken willst, jedoch in einem falschen Scope – sie wird darüber hinaus nicht konserviert.
Lies dir mal Organisation von JavaScripten: Module und Kapselung durch. Beschäftige dich mit dem Revealing Module Pattern oder Konstruktoren, Prototypen und Instanzen, um Variablen nur für bestimmte Funktionen zugänglich zu machen, aber nach außen hin zu kapseln.
Zum Hintergrund ist auch dieser (fortgeschrittene) Artikel interessant: Die Grundlagen von JavaScript.
Mathias
Oh, damit, dass da kurz vor Mitternacht noch was kommt, hatte ich nicht gerechnet ^^
Danke für Deine Antwort, molily!
Erkläre es trotzdem mal, denn das ist die Ursache des Problems.
Also: ich vereinfache mal die Sachlage so gut es geht auf das Wesentliche:
Ich habe eine library, die so ähnlich wie jquery funktioniert - ich nenne sie hier mal M.
Will ich beispielsweise alle HTML-Elemente der Klasse 'drag' draggable machen,
so notiere ich: M('.drag').drag(/*obj-lit.*/); als Parameter kann optional ein Objekt-Literal mit Spezifikationen übergeben werden
( call-back-functions etc. ).
drag : function( params ) {
// params ist ein Objekt-Literal, das hier ausgewertet, ggf mit defaults
// gefüllt wird
// die an anderer Stelle gespeicherten Elemente werden "geholt" und in einer
// for-Schleife wird diesen per addEventListener eine Event-Funktion (down) on 'mousedown' zugewiesen
// in der funktion down werden die Parameter, die an drag übergeben wurden, verarbeitet und es werden die Aktionen für 'mousemove' und 'mouseup' definiert.
}
Ich hatte die Funktion down zunächst im scope von drag, damit diese Zugriff auf die Parameter hat,
weil ich bei der Notation addEventListener('mousedown',down,true) keine Parameter übergebe und
andererseits bei einer Kapselung per anonymer Funktion diese ja wieder verloren geht (weil namenlos) -
wobei ich übersehen hatte, dass diese Funktion ja bei jedem Aufruf von drag eine neue ist und mein removeEventListener-Versuch natürlich fehlschlägt.
Wie gesagt: Etwas ganz Wesentliches übersehen - hätte ich eigentlich selber erkennen müssen :/
Lieben Gruß