2009-11-19 6 views
3

Un exemple simplifié:Référence extérieur objet fonction de rappel ajax

// Let's create a new object 
function MyObject() { 
    // 
} 

// Add some method to this object 
MyObject.prototype.myFunctionA = function() { 
    // 
} 

// Another method 
MyObject.prototype.myFunctionB = function(arg) { 
    // AJAX GET request   
    $.get('script.php', { par : arg }, function(data) { 

     // and here in the callback function  
     // I need to call MyObject.prototype.myFunctionA method! 
     // but "this" references callback function so 
     // I don't know how to access MyObject here 

    }); 
} 

J'ai expliqué mon problème dans les commentaires. Comment puis je faire ça?

Répondre

7

simple:

// Let's create a new object 
function MyObject() { 
    // 
} 

// Add some method to this object 
MyObject.prototype.myFunctionA = function() { 
    // 
} 

// Another method 
MyObject.prototype.myFunctionB = function(arg) { 
    // AJAX GET request  
    var me = this; 
    $.get('script.php', { par : arg }, function(data) { 
     // use me.something instead of this.something 
    }); 
} 

réutilisable (en utilisant la portée de piégeage):

function createDelegate(obj, handler) 
{ 
    return function() { 
     handler.apply(obj, arguments); 
    } 
} 

puis

MyObject.prototype.myFunctionB = function(arg) { 
    // AJAX GET request  
    var me = this; 
    $.get(
     'script.php', 
     { par : arg }, 
     createDelegate(this, function(data) { 
     // use this.something 
     }) 
    ); 
} 

Ainsi, un code en relation avec les commentaires ci-dessous, createDelegate peut également être utilisé dans quelques dif façons férents, dont un être:

function createDelegate(obj, handler) 
{ 
    handler = handler || this; 
    return function() { 
     handler.apply(obj, arguments); 
    } 
} 

Function.prototype.createDelegate = createDelegate; 

cela vous permet de faire des choses comme:

var someObj = {a:1, b:function() {return this.a;}}; 
var scopedDelegateForCallback = someObj.b.createDelegate(whateverobj) 

vous pouvez faire des tours pour obtenir aussi des parents, mais c'est trop pour moi à embêter avec atm.

ou, vous pouvez faire quelque chose comme ceci:

function createDelegate(handler, obj) 
{ 
    obj = obj || this; 
    return function() { 
     handler.apply(obj, arguments); 
    } 
} 

Object.prototype.createDelegate = createDelegate; 

et de l'utiliser:

someObj.createDelegate(someObj.b); 

ou peut-être:

function createDelegateForMember(handlerName, obj) 
{ 
    obj = obj || this; 
    return function() { 
     obj[handlerName].apply(obj, arguments); 
    } 
} 

Object.prototype.createDelegate = createDelegateForMember; 

puis

someobj.createDelegate("b"); 
+0

J'aime votre fonction 'createDelegate', mais je pense que ce serait encore mieux si vous déplaciez le paramètre' obj' à la fin de la liste de paramètres et que vous le rendiez facultatif, par défaut 'this'. Cela permettrait d'économiser du code dans le cas d'utilisation le plus courant. – bcat

+0

si vous ne spécifiez pas 'ceci', il est inutile d'utiliser la fonction createDelegate :) –

+0

Non, je voulais dire quelque chose comme ceci: 'function createDelegate (gestionnaire, obj) {return function() {handler.apply (obj || ceci, arguments); } } '. Et l'appelant comme ceci: '$ .get ('script.php', {par: arg}, createDelegate (fonction (données) {/ * faire quelque chose * /})); – bcat

6

Vous pouvez affecter "var self = this" dans MyObject.prototype.myFunctionB avant d'appeler le $ .get puis vous pouvez utiliser l'alias "self" dans le rappel.

MyObject.prototype.myFunctionB = function(arg) { 
    var self = this; 

    $.get('script.php', { par : arg }, function(data) { 
     alert(self); 
    }); 
} 
+0

propre et simple. Très bonne réponse! –

4

fonctions JavaScript "close over" des variables dans les étendues extérieures, de sorte que vous pouvez faire:

// Another method 
MyObject.prototype.myFunctionB = function(arg) { 
    // Save `this` reference for use in callback. 
    var that = this; 

    // AJAX GET request 
    $.get('script.php', { par : arg }, function(data) { 

     // Now `that` holds the contents of the current `MyObject`. 
     // So you can call other methods. 
     that.myFunctionA(); 
     // ... etc ... 

    }); 
} 
+0

+1 pour le lien vers l'explication de fermeture –