2010-05-11 4 views
8

je fais quelques appels Ajax à l'intérieur d'un objet javascript .:XMLHttpRequest intérieur d'un objet: comment garder la référence à « ce »

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

Dans la fonction onreadystatechange, cela ne fait pas référence à l'objet principal plus , donc je n'ai pas accès à this.foo. Puis-je conserver la référence à l'objet principal dans les événements XMLHttpRequest?

Répondre

7

L'approche la plus simple est généralement de stocker la valeur de this sur une variable locale:

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

Je pense aussi que votre identifiant myObject est vraiment un constructor function (vous assignez une propriété prototype).

Si c'est le cas, n'oubliez pas d'inclure la bonne propriété constructor (puisque vous remplacez l'entier prototype), qui est simplement une référence au constructeur.

Peut-être hors-sujet à cette question, mais recommandé de lire:

4

Une autre solution simple est de lier votre fonction onreadystatechange à ce sujet. bind -si la fonction fait essentiellement la même chose que dans la réponse de CMS (c'est-à-dire ajouter la valeur à la fermeture), mais bind le fait de manière transparente: vous continuez à utiliser this au lieu de définir une variable instance.

Voici une implémentation Function#bind si votre base de code ne comprend pas un:

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

Et voici comment vous pouvez l'utiliser dans votre code:

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

Je recommande fortement de vérifier Si la méthode 'Function.prototype.bind' existe avant de la créer, car elle fait partie du standard ECMAScript 5th Edition et qu'elle est implémentée par tous les principaux fournisseurs de navigateurs, bientôt une implémentation native sera disponible et vous ne voulez pas remplacez-le par le vôtre: [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/problèmes/détail? id = 384). – CMS

Questions connexes