2008-10-23 9 views
19

¿Existe alguna forma recomendada o común en JavaScript para que los miembros de la clase actúen como controladores de eventos?¿Métodos de clase como controladores de eventos en JavaScript?

Considere el siguiente ejemplo:

<head> 
    <script language="javascript" type="text/javascript"> 

     ClickCounter = function(buttonId) { 
      this._clickCount = 0; 
      document.getElementById(buttonId).onclick = this.buttonClicked; 
     } 

     ClickCounter.prototype = { 
      buttonClicked: function() { 
       this._clickCount++; 
       alert('the button was clicked ' + this._clickCount + ' times'); 
      } 
     } 

    </script> 
</head> 
<body> 
    <input type="button" id="btn1" value="Click me" /> 
    <script language="javascript" type="text/javascript"> 
     var btn1counter = new ClickCounter('btn1'); 
    </script> 
</body> 

El controlador de eventos buttonClicked se llama, pero el miembro _clickCount es inaccesible, o esta puntos a algún otro objeto.

¿Algún buen consejo/artículos/recursos acerca de este tipo de problemas?

Respuesta

17
ClickCounter = function(buttonId) { 
    this._clickCount = 0; 
    var that = this; 
    document.getElementById(buttonId).onclick = function(){ that.buttonClicked() }; 
} 

ClickCounter.prototype = { 
    buttonClicked: function() { 
     this._clickCount++; 
     alert('the button was clicked ' + this._clickCount + ' times'); 
    } 
} 
+0

Gracias por su solución. También estoy tratando de entender el panorama general: patrones, prácticas, etc. ¿Algún artículo bueno que conozca? – JacobE

+5

esto es genial: http://ejohn.org/apps/learn/ – pawel

+8

Este es un buen ejemplo, pero esta respuesta podría ser mejor con alguna explicación de por qué es una buena solución, para los novatos de por aquí. –

5

Una función unida directamente a la propiedad onclick tendrá que apunta this la propiedad del contexto de ejecución en el elemento.

Cuando necesite un evento elemento para funcionar en una instancia específica de un objeto (al estilo de un delegado en .NET), entonces tendrá un cierre: -

function MyClass() {this.count = 0;} 
MyClass.prototype.onclickHandler = function(target) 
{ 
    // use target when you need values from the object that had the handler attached 
    this.count++; 
} 
MyClass.prototype.attachOnclick = function(elem) 
{ 
    var self = this; 
    elem.onclick = function() {self.onclickHandler(this); } 
    elem = null; //prevents memleak 
} 

var o = new MyClass(); 
o.attachOnclick(document.getElementById('divThing')) 
+0

¡Esto es exactamente lo que estaba buscando! ¡Gracias! – Jeremy

0

No sé ¿Por qué Function.prototype.bind no fue mencionado aquí todavía? Así que voy a dejar esto aquí;)

ClickCounter = function(buttonId) { 
    this._clickCount = 0; 
    document.getElementById(buttonId).onclick = this.buttonClicked.bind(this); 
} 

ClickCounter.prototype = { 
    buttonClicked: function() { 
     this._clickCount++; 
     alert('the button was clicked ' + this._clickCount + ' times'); 
    } 
} 
1

puede utilizar la sintaxis de grasa de flecha, que se une al ámbito léxico de la función

function doIt() { 
    this.f =() => { 
    console.log("f called ok"); 
    this.g(); 
    } 
    this.g =() => { 
    console.log("g called ok"); 
    } 
} 

Después de que se puede tratar

var n = new doIt(); 
setTimeout(n.f,1000); 

Puede probarlo en babel o si su navegador es compatible con ES6 en jsFiddle.

Desafortunadamente, la clase-ESntanta ES6 no parece permitir la creación de una función vinculada léxicamente a esto. Personalmente creo que bien podría hacer eso. EDITAR: Parece que hay experimental ES7 feature to allow it.

Cuestiones relacionadas