2009-11-26 23 views
7

Tengo un objeto flash de terceros que puedo manipular a través de una API de JavaScript que proporcionan. Estoy tryind para escuchar un evento en este objeto y luego disparar evento dentro de mi objeto para impulsar aún más el evento. Resulta que estoy usando EXT Js, pero no creo que sea importante aquí.addEventListener y el alcance de este

Código de ejemplo

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

Mi problema es que 'esto' dentro de la función anónima se refiere al objeto que generó el evento en lugar de mi objeto que quiero para disparar un evento sobre.

Su otro problema de alcance. Gracias de antemano por cualquier ayuda.

Respuesta

0

Este es el típico enfoque a este problema: -

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

Prefiero 'var self = this;'. Crear una función y luego ejecutarla mientras pasa 'this' ya que el parámetro parece un poco por la borda; el código también es un poco más largo ;-) –

+0

@Andy: Sí, a menudo también hago eso cuando el código existe en un contexto de ejecución pequeño. Sin embargo, lo anterior es el enfoque estándar que funciona en una variedad más amplia de escenarios.El alcance del identificador "self" está limitado solo al cierre, no hay peligro de que el código subsiguiente pueda modificar el valor contenido en él antes de que se desate el evento. Esto no es cierto para el enfoque 'var self = this;'. – AnthonyWJones

12

¿Qué hay de la creación de una variable externa antes de hacer referencia a 'este' objeto. Por ejemplo:

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

Sí, esta es la expresión normal. La variable de cierre a menudo se llama 'that' o' self' (aunque no creo que esta última sea una gran idea ya que 'self' tiene un significado establecido, aunque inútil, en JavaScript). – bobince

+0

OK que funciona. Fuera de interés, hay otra forma que no sea establecer una variable para esto. Por ejemplo, utilizando el cierre? – Jonnio

+1

@bobince: Prefiero 'self'. 'self' está expuesto por' window' como una referencia a sí mismo. Me complace reutilizar el identificador en otros ámbitos. Me parece que tiene el significado correcto y no choca con eso, significa que "yo" también es la ventana. – AnthonyWJones

5

Mientras que las otras respuestas lograr lo que necesitaba, que no funcionan de la manera más eficiente (escalable) , porque finalmente no desacoplan el objeto de vista (this.chart) de la lógica de esa vista (fireEvent()). En las aplicaciones MVC, estas "decisiones" de vista residen en un controlador . El controlador "controla" vistas y debe contener todas las API a las que puede acceder la vista.

En su ejemplo, this es el controlador, y eso está bien (significa que está agregando sus oyentes en el lugar correcto). Todo lo que necesita hacer es obligar a la manejador al ámbito de lo que debe hacer el "manejo" - en su caso: this:

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

Lo que las otras respuestas en esta página han hecho que se hace para que su vista se convierta en su propio controlador, pero solo mientras maneja eventos 'crear', asignando una referencia temporal al "controlador" usando var self = this. Nuevamente, esto funciona bien, pero no funciona bien a escala en aplicaciones basadas en eventos, y realmente no tiene sentido si tiene que manejar muchos eventos.

.bind() es una implementación de ECMAScript 5. Si es necesario trabajar en navegadores aún más antiguos, aquí se describe un buen método para hacerlo (usando functions y .call()): https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind

+0

En algunas implementaciones de MVC (como en el ejemplo descrito aquí: http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller), el controlador en sí mismo (por ejemplo, su '.fireEvent () ') se define en la vista, pero el controlador lo invoca según sea necesario. Esto podría permitirle no usar '.bind()' o una referencia automática, pero haría que su manejador sea muy poco modular; y su aplicación crecerá muy grande. – Benny