2010-05-11 7 views
8

hago algunas llamadas Ajax desde el interior de un objeto Javascript .:XMLHttpRequest dentro de un objeto: cómo mantener la referencia a "este"

myObject.prototye = { 
    ajax: function() { 
    this.foo = 1; 

    var req = new XMLHttpRequest(); 
    req.open('GET', url, true); 
    req.onreadystatechange = function (aEvt) { 
     if (req.readyState == 4) { 
     if(req.status == 200) { 
      alert(this.foo); // reference to this is lost 
     } 
     } 
    } 
}; 

Dentro de la función onreadystatechange, esto no se refiere al objeto principal ya , entonces no tengo acceso a esto. ¿Puedo guardar la referencia al objeto principal dentro de los eventos XMLHttpRequest?

Respuesta

7

El enfoque más simple es generalmente para almacenar el valor de this en una variable local:

myObject.prototype = { 
    ajax: function (url) { // (url argument missing ?) 
    var instance = this; // <-- store reference to the `this` value 
    this.foo = 1; 

    var req = new XMLHttpRequest(); 
    req.open('GET', url, true); 
    req.onreadystatechange = function (aEvt) { 
     if (req.readyState == 4) { 
     if (req.status == 200) { 
      alert(instance.foo); // <-- use the reference 
     } 
     } 
    }; 
    } 
}; 

Sospecho también que su identificador myObject es realmente un constructor function (está asignando una propiedad prototype).

Si ese es el caso, no olvide incluir la propiedad constructor (ya que está reemplazando la prototype), que es simplemente una referencia de regreso al constructor.

Tal vez fuera del tema de este problema, pero se recomienda leer:

4

Otra solución simple es vincular a su función onreadystatechange a esto. bind -siendo que la función hace básicamente lo mismo que en la respuesta de CMS (es decir, agregando el valor al cierre), pero bind lo hace de forma transparente: sigue usando this en lugar de establecer una variable instance.

Aquí es una aplicación Function#bind si su base de código no incluye uno:

Function.prototype.bind = function(obj) { 
    var __method = this; 
    var args = []; for(var i=1; i<arguments.length; i++) args.push(arguments[i]); 
    return function() { 
     var args2 = []; for(var i=0; i<arguments.length; i++) args2.push(arguments[i]); 
     return __method.apply(obj, args.concat(args2)); 
    }; 
} 

Y aquí es cómo se puede utilizar en su código:

myObject.prototype = { 
    ajax: function() { 
    this.foo = 1; 

    var req = new XMLHttpRequest(); 
    req.open('GET', url, true); 
    req.onreadystatechange = function (aEvt) { 
     if (req.readyState == 4) { 
     if(req.status == 200) { 
      alert(this.foo); // reference to this is *kept* 
     } 
     } 
    }.bind(this) // <- only change 
    } 
}; 
+0

recomendaría encarecidamente comprobar si el método 'Function.prototype.bind' existe antes de crearlo, porque forma parte del Estándar ECMAScript 5th Edition y está siendo implementado por todos los principales proveedores de navegadores, pronto estará disponible una implementación nativa y usted no querrá anótalo con el tuyo: [WebKit] (https: // bugs.webkit.org/show_bug.cgi?id=26382), [Mozilla] (https://bugzilla.mozilla.org/show_bug.cgi?id=429507), [Google V8] (http://code.google .com/p/v8/issues/detail? id = 384). – CMS

Cuestiones relacionadas