Come posso avere setTimeout eseguire un metodo in un oggetto?
-
21-09-2019 - |
Domanda
Mi piacerebbe avere un menu a tendina si chiude su un evento mouseLeave, dopo un breve ritardo. Ma sto avendo problemi a farlo funzionare.
Si considerino i seguenti metodi di un oggetto: (sto usando jQuery)
myObj = {};
myObj.message = "woot!";
myObj.bindEvents = function() {
var that = this;
$("#menuPanel")
.bind("mouseleave", function() {
that.timer = setTimeout(that.closeMenu,500);
});
}
myObj.closeMenu = function() {
// close the menu
alert(this.message);
}
Questo non funziona. Vale a dire, this.message viene in su non definito. Dopo un po 'di scavo, capisco perché. :) Il 'che' riferimento non è disponibile per codice all'interno del setTimeout al momento dell'esecuzione.
Mi chiedo, qual è il modo "migliore" per aggirare questo tipo di problema? Come posso avere un metodo che utilizza setTimeout chiamare un altro metodo nello stesso oggetto, e hanno ancora accesso alle proprietà nell'oggetto?
Grazie in anticipo per il vostro aiuto.
Soluzione
Il problema qui è che si sta staccando il metodo closeMenu da esso dell'oggetto. Si avrebbe lo stesso problema se avete fatto questo:
var closeMenu = myObj.closeMenu; // detaching the method from the object
closeMenu();
Come staccare e chiamare i metodi come questo significa che non sono più applicabili agli oggetti sono stati creati su. Nel tuo esempio, si sta facendo quasi la stessa cosa:
// Setting the first parameter of setTimeout to be the detached closeMenu method
that.timer = setTimeout(that.closeMenu,500);
Una correzione per il primo metodo sarebbe quello di utilizzare i metodi call
o apply
:
var closeMenu = myObj.closeMenu; // detaching the method from the object
closeMenu.apply(myObj);
Ma questo non avrebbe funzionato per un timer. Invece, creare una funzione anonima:
that.timer = setTimeout(function () { that.closeMenu(); },500);
Potrebbe anche essere degno di nota
bind()
- da non confondere con la $('#selector').bind()
di jQuery - un metodo che è stato galleggianti intorno su vari blog e in alcune librerie (Prototype è il più importante) per un po 'di tempo, ed è stato infine implementato nel edizione ECMAScript 5 .
that.timer = setTimeout(that.closeMenu.bind(that),500);
Io uso un metodo simile a una o due classi che ho creato, perché rende solo le cose più facili.