Domanda

questa cosa quasi funziona:

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

Quindi è altro che abbia per oggetto XMLHttpRequest come membro della mia classe, anziché globalmente definito, e invocando nel modo tradizionale. tuttavia, dentro la mia funzione di callback ConnectionEvent, il significato di "questo" si perde, anche se la funzione stessa è ambito all'interno myClass. Ho anche fatto in modo che l'oggetto che ho un'istanza di da myClass è mantenuto abbastanza a lungo in vita (dichiarata globale nello script).

In tutti gli esempi di utilizzo di classi JavaScript che ho visto, "questo" era ancora disponibile all'interno delle funzioni interne. per me, non lo è, anche se prendo la mia funzione di fuori e ne fanno un myClass.prototype.connectionEvent. Che cosa sto facendo di sbagliato? grazie.

È stato utile?

Soluzione

La ragione che non funziona è che in Javascript, this è definita interamente dal modo in cui una funzione è chiamato , non dove è definito. Questo è diverso rispetto ad alcune altre lingue.

Per avere this dire quello che ci si aspetta, che avrebbe dovuto garantire che in modo esplicito dal "legame" che:

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);
    };

C'è ulteriori informazioni sulla gestione this in questo post del blog , ma fondamentalmente: Quando viene chiamata una funzione senza particolare sforzo per this set, this all'interno della funzione sarà sempre l'oggetto globale (window, sui browser). Ci sono due modi per this insieme Quando si effettua una chiamata:

  1. Uso Function#call (o Function#apply) come ho fatto sopra, passando il riferimento all'oggetto da utilizzare come this come primo parametro. Che chiama la funzione e imposta this a tutto ciò che avete passato. La differenza tra #call e #apply è il modo per fornire ulteriori argomenti da passare alla funzione. Con #call li forniti come ulteriori argomenti alla chiamata #call (ad esempio func.call(thisArg, arg0, arg1, arg2)), mentre con #apply loro fornite come un array nel secondo argomento (func.apply(thisArg, [arg0, arg1, arg2])).
  2. Utilizzo di notazione: se si dispone di un oggetto che ha una proprietà con una funzione ad esso assegnata (come la vostra proprietà start), definendolo utilizzando l'istanza dell'oggetto, un punto, e il nome della proprietà (this.start() o foo.start(), ecc .) chiamerà la funzione e impostare this all'istanza oggetto all'interno della chiamata. Così la notazione fa due del tutto distinti le cose: guarda in alto la proprietà e trova una funzione come il suo valore, e chiama la funzione in modo tale che this è impostato per l'oggetto durante la chiamata. Letteralmente è come:. var f = obj.func; f.call(obj)

Un po 'off-topic, ma: A meno di un buon motivo per, non vorrei reinventare questa ruota. Ci sono un sacco di librerie là fuori per le chiamate semplicemente XHR. jQuery , Prototype , chiusura , e quasi tutto il resto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top