2011-08-08 16 views
12

defino la siguiente MyClass y sus métodos en una secuencia de comandos de usuario:invocar un método de objeto javascript desde el interior de una devolución de llamada

function MyClass() { 
    this.myCallback = function() { 
     alert("MyClass.myCallback()"); 
    }; 

    this.startRequest = function() { 
     GM_xmlhttpRequest({ 
      'method': 'GET', 
      'url': "http://www.google.com/", 
      'onload': function (xhr) { 
       myClassInstance.myCallback(); 
      } 
     }); 
    }; 
} 

var myClassInstance = new MyClass(); 
myClassInstance.startRequest(); 

Este script funciona y el método myCallback() es llamada una vez que los GM_xmlhttpRequest ultima.

Sin embargo, solo funciona porque la devolución de llamada onload hace referencia a la variable global myClassInstance. Si actualizo a la devolución de llamada onload:

'onload': function (xhr) { 
    this.myCallback(); 
} 

Luego llego el (Chrome) Error:

Uncaught TypeError: Object [object DOMWindow] has no method 'myCallback'.

Parece está siendo evaluado this en el contexto equivocado.

¿Hay alguna manera de invocar el método myCallback() de myClassInstance sin tener que recurrir al uso de una variable global?

Respuesta

23

Guarde el this correcto, cuando esté dentro del alcance, en una variable. A continuación, puede hacer referencia a ella más tarde:

this.startRequest = function() { 
    var myself = this; 
    GM_xmlhttpRequest({ 
     'method': 'GET', 
     'url': "http://www.google.com/", 
     'onload': function (xhr) { 
      myself.myCallback(); 
     } 
    }); 
}; 
+0

+1 golpéame. – JAAulde

+4

+1 Acabas de terminar mi sesión de slamming de cabeza de una hora larga. Gracias. :) – Anthony

2

almacenar una referencia a la instancia y utilizarla:

function MyClass() { 
    this.myCallback = function() { 
     alert("MyClass.myCallback()"); 
    }; 

    var instance = this; 

    instance.startRequest = function() { 
     GM_xmlhttpRequest({ 
      'method': 'GET', 
      'url': "http://www.google.com/", 
      'onload': function (xhr) { 
       instance.myCallback(); 
      } 
     }); 
    }; 
} 
4

La solución más simple, como ya se ha señalado, es la creación de un alias para el this que se mantiene en alcance. Los nombres de variables más populares para el alias son cosas como self o that, pero todo funciona, realmente.

La otra alternativa (que puede o no puede ser mejor, en función del caso de uso) es vinculante el método en una función de "simple" y el uso que en lugar:

var f = this.callback.bind(this); 

... 
'onload': function(){ 
    f(); 
} 

bind no se admite en edad navegadores, pero puedes encontrar alternativas en muchos frameworks JS. El ejemplo que di no se ve tan bien, pero puede ser muy conveniente cuando quieres pasar tu método directamente como función de devolución de llamada (también puedes obtener una aplicación de función parcial y eso es muy claro)

+2

Tenga cuidado con 'self' debido a' window.self'. – Jeremy

Cuestiones relacionadas