clase de JavaScript XMLHttpRequest llamar internamente, entonces el manejo onreadystatechange
-
26-09-2019 - |
Pregunta
esta cosa casi funciona:
function myClass(url) {
this.source = url;
this.rq = null;
this.someOtherProperty = "hello";
// open connection to the ajax server
this.start = function() {
if (window.XMLHttpRequest) {
this.rq = new XMLHttpRequest();
if (this.rq.overrideMimeType)
this.rq.overrideMimeType("text/xml");
} else
this.rq = new ActiveXObject("Microsoft.XMLHTTP");
try {
this.rq.onreadystatechange = connectionEvent;
this.rq.open("GET", this.source, true);
this.rq.send(null);
this.state = 1;
} catch (err) {
// some error handler here
}
}
function connectionEvent() {
alert("i'm here");
alert("this doesnt work: " + this.someOtherProperty);
}
} // myClass
por lo que no es nada más que tener el objeto XMLHttpRequest como miembro de mi clase, en lugar de a nivel mundial definido, y que lo alega, de la manera tradicional. Sin embargo, dentro de mi función de devolución de llamada ConnectionEvent, el significado de "este" se pierde, a pesar de que la función en sí está en el ámbito interior myClass. i también se aseguró de que el objeto que crear una instancia de myClass se mantiene con vida el tiempo suficiente (declarado global en el guión).
en todos los ejemplos de la utilización de clases de javascript que he visto, "esto" era todavía disponibles dentro de las funciones internas. para mí, no lo es, incluso si me tomo mi función fuera y convertirlo en un myClass.prototype.connectionEvent. ¿Qué estoy haciendo mal? gracias.
Solución
La razón por la que no funciona es que en Javascript, this
se define en su totalidad por la forma de una función es llamada , no en donde está definido. Esto es diferente a otros idiomas.
Para tener this
media lo que espera, usted tendría que asegurarse de que explícitamente por "unión" que:
this.start = function() {
var self = this; // Set up something that survives into the closure
/* ...lots of stuff omitted... */
this.rq.onreadystatechange = function() {
// Call `connectionEvent`, setting `self` as `this` within the call
connnectionEvent.call(self);
};
Hay más información acerca de la gestión this
en esta entrada del blog , pero básicamente: Cuando se invoca una función sin ningún esfuerzo especial de que se establezca this
, this
dentro de la función será siempre el objeto global (window
, en los navegadores). Hay dos maneras de configurar this
al hacer una llamada:
- Uso
Function#call
(oFunction#apply
) como lo hice anteriormente, que pasa en la referencia de objeto que se utiliza comothis
como el primer parámetro. Que llama a la función y conjuntosthis
a lo que se ha pasado. La diferencia entre#call
y#apply
es la forma de suministro adicional argumentos para pasar a la función. Con#call
que les suministran como argumentos adicionales a la llamada (por ejemplo#call
func.call(thisArg, arg0, arg1, arg2)
), mientras que con#apply
que les suministran como una matriz en el segundo argumento (func.apply(thisArg, [arg0, arg1, arg2])
). - Uso de notación: Si usted tiene un objeto que tiene una propiedad con una función asignada a ella (como su propiedad
start
), que calificó mediante el uso de la instancia del objeto, un punto y el nombre de la propiedad (this.start()
ofoo.start()
, etc. .) llamará a la función y el conjunto dethis
a la instancia del objeto dentro de la llamada. Por lo que la notación hace dos completamente distintas cosas: busca la propiedad y se encuentra una función como su valor, y llama a la función tal quethis
se establece en el objeto durante la llamada. Literalmente es como:.var f = obj.func; f.call(obj)
Un poco fuera de tema, pero: Salvo una muy buena razón para, yo no reinventar esta rueda. Hay un montón de bibliotecas que hay para llamadas con sólo XHR. jQuery , Prototype , Cierre , y casi todo el resto.