2009-11-26 16 views
7

Ho un oggetto flash di terze parti che posso manipolare tramite un'API javascript fornita. Sto provando ad ascoltare un evento su questo oggetto e poi a lanciare un evento all'interno del mio oggetto per far scoppiare l'evento. Mi è capitato di usare EXT Js ma non penso sia importante qui.addEventListener e lo scopo di questo

codice di esempio

this.chart.addEventListener('create', function() { 
    this.fireEvent('created'); 
}, false) 

mio problema è che 'questo' all'interno della funzione anonima si riferisce all'oggetto che ha generato l'evento piuttosto che il mio oggetto che voglio generare un evento on.

L'ennesimo problema di ambito. Grazie in anticipo per qualsiasi aiuto.

risposta

0

Questo è l'approccio tipico a questo problema: -

(function(self) { 
    self.chart.addEventListener('create', function() {self.fireEvent('created');}, false); 
})(this); 
+2

Preferisco 'var auto = this;'. Creare una funzione e poi eseguirla mentre si passa 'this' come il parametro sembra un po 'fuori bordo - il codice è leggermente più lungo ;-) –

+0

@Andy: Sì lo faccio spesso anche quando il codice esiste in un contesto di esecuzione ridotto. Tuttavia, quanto sopra è l'approccio standard che funziona in una più ampia varietà di scenari.Lo scopo dell'identificatore 'self' è limitato solo alla chiusura, non c'è pericolo che il codice successivo possa modificare il valore contenuto in esso prima che l'evento venga attivato. Questo non è vero per l'approccio 'var self = this;'. – AnthonyWJones

12

Che dire creare una variabile esterna prima di fare riferimento a "questo" oggetto. Per esempio:

var _this = this; 
this.chart.addEventListener('create', function() { _this.fireEvent('created'); }, false) 
+4

Sì, questo è l'idioma normale. La variabile di chiusura viene spesso chiamata 'that' o' self' (anche se non penso che quest'ultima sia una grande idea come 'self' ha un significato stabilito, anche se inutile, in JavaScript). – bobince

+0

OK, funziona. Di interesse c'è un altro modo oltre a impostare una variabile per questo. Ad esempio usando la chiusura? – Jonnio

+1

@bobince: preferisco 'self'. 'self' è esposto da' window' come riferimento a se stesso. Sono abbastanza felice di riutilizzare l'identificatore in altri ambiti. Mi sembra che abbia il significato giusto e non si scontri con ciò significa che anche se "self" capita di essere la finestra. – AnthonyWJones

5

Mentre le altre risposte realizzare quello che avevi bisogno, che non funzionano nel modo più efficiente (scalabile) , perché in definitiva non disaccoppiano l'oggetto vista (this.chart) dalla logica di quella vista (fireEvent()). Nelle applicazioni MVC, queste "decisioni" vengono visualizzate in un controller . Il controller "controlla" le viste e dovrebbe contenere tutte le API a cui la vista può accedere.

Nel tuo esempio, this è il controller, e va bene (vuol dire che stai aggiungendo gli ascoltatori nel posto giusto). Tutto ciò che dovete fare è associare il gestore per la portata della cosa che dovrebbe fare il "trattamento" - nel vostro caso: this:

// `this` is the controller of `chart` 
this.chart.addEventListener('create', function() { 
    this.fireEvent('created'); 
}.bind(this)); 

Quali le risposte su questa pagina hanno fatto è reso quindi la visualizzazione diventa il proprio controller, ma solo durante la gestione degli eventi di 'creazione', assegnando un riferimento temporaneo al "controller" utilizzando var self = this. Di nuovo, questo funziona bene, ma non funziona bene su larga scala in applicazioni event-driven, e non ha senso se si hanno molti eventi da gestire.

.bind() è un'implementazione di ECMAScript 5. Se è necessario lavorare anche con i browser più vecchi, qui viene descritto un buon metodo (utilizzando functions e .call()): https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind

+0

In alcune implementazioni MVC (come nell'esempio qui descritto: http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller), il gestore stesso (ad esempio il tuo '.fireEvent () ') è definito nella vista, ma il controller lo richiama come necessario. Questo potrebbe permetterti di non usare affatto ".bind()" o un riferimento personale, ma renderebbe il tuo gestore molto non modulato; e la tua applicazione diventerebbe molto grande. – Benny