Question

cette chose fonctionne presque:

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

donc rien de plus que d'avoir l'objet XMLHttpRequest en tant que membre de ma classe, au lieu de définir globalement, et en invoquant de la manière traditionnelle. Cependant, dans ma fonction de rappel ConnectionEvent, le sens de « ce » est perdu, même si la fonction elle-même est à l'intérieur scope myClass. J'ai aussi assuré que l'objet que j'instancier de myClass est maintenu en vie assez longtemps (déclarée mondiale dans le script).

dans tous les exemples de l'utilisation des classes javascript que j'ai vu, « ce » était encore disponible à l'intérieur des fonctions internes. pour moi, ce n'est pas, même si je prends ma fonction en dehors et en faire un myClass.prototype.connectionEvent. Qu'est-ce que je fais mal? je vous remercie.

Était-ce utile?

La solution

La raison pour laquelle il ne fonctionne pas est que Javascript, this est définie entièrement par la façon dont la fonction est appelé , pas là où il est défini. Ceci est différent que d'autres langues.

Pour avoir this moyenne ce que vous attendez, vous auriez à faire en sorte que explicitement par « liant » il:

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

Il y a plus d'informations sur la gestion des this ce blog , mais au fond: Lorsqu'une fonction est appelée sans aucun effort particulier fait à this ensemble, this dans la fonction sera toujours l'objet global (window, sur les navigateurs). Il y a deux façons de this ensemble lors d'un appel:

  1. Utilisation Function#call (ou Function#apply) comme je l'ai fait ci-dessus, en passant dans la référence d'objet à utiliser comme this comme premier paramètre. Qui appelle la fonction et des ensembles this à tout ce que vous avez passé. La différence entre #call et #apply est de savoir comment vous fournir d'autres arguments pour passer dans la fonction. Avec #call vous les fournissez comme d'autres arguments à l'appel #call (par exemple func.call(thisArg, arg0, arg1, arg2)), alors qu'avec #apply vous les fournir sous forme de tableau dans le second argument (func.apply(thisArg, [arg0, arg1, arg2])).
  2. En utilisant la notation en pointillé: Si vous avez un objet qui a une propriété avec une fonction qui lui est assignée (comme votre propriété start), appelant à l'aide de l'instance d'objet, d'un point, et le nom de la propriété (this.start() ou foo.start(), etc. .) appelle la fonction et jeu this à l'instance d'objet dans l'appel. Ainsi, la notation en pointillés fait deux tout à fait distincts choses: recherche la propriété et trouve une fonction de sa valeur, et appelle la fonction telle que this est définie sur l'objet pendant l'appel. Littéralement c'est comme:. var f = obj.func; f.call(obj)

Un peu hors-sujet, mais: À moins d'une très bonne raison, je ne réinventer cette roue. Il y a beaucoup de bibliothèques là-bas pour les appels simplement XHR. jQuery , Prototype , Fermeture , et presque tout le reste.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top