2009-04-10 9 views
1

Je cette classe où je suis en utilisant une combinaison de jQuery et Prototype:Problème de variable "this" remplacé ou comment appeler une fonction membre?

var MyClass = Class.create({ 
    initElements: function(sumEl) { 
     this.sumEl = sumEl; 
     sumEl.keyup(this.updateSumHandler); 
    }, 

    updateSumHandler: function(event) { 
     // Throws error here: "this.updateSum is not a function" 
     this.updateSum(); 
    }, 

    updateSum: function() { 
     // does something here 
    } 
}); 

Comment puis-je appeler this.updateSum() après tout?

Répondre

5

Vous devez utiliser des fermetures.

initElements: function(sumEl) { 
     this.sumEl = sumEl; 
     var ref = this; 
     sumEl.keyup(function(){ref.updateSumHandler();}); 
}, 
0

Il est le fameux Javascript idiome vous devez utiliser en initElements fonction:

var that = this; 

plus tard dans votre gestionnaire juste se référer à that au lieu de this:

var MyClass = Class.create({ 
    initElements: function(sumEl) { 
     this.sumEl = sumEl; 
     var that = this; 
     sumEl.keyup(this.updateSumHandler); 
    }, 
    updateSumHandler: function(event) { 
     that.updateSum(); 
    }, 
    updateSum: function() { 
     // does something here 
    } 
}); 

Il était couvert en grand détail dans talk by Stuart Langridge sur Fermetures Javascript à Fronteers Conférence 2008

+0

Votre 'that' n'est pas visible dans' updateSumHandler'. –

+0

Non, pourquoi? C'est une fermeture donc ça devrait être dans la portée de updateSumHandler. N'a pas testé ce code, cependant. –

4

suggestion totalement non testé:

sumEl.keyup(this.updateSumHandler.bind(this)); 

.bind() redonne une nouvelle fonction où le premier paramètre de bind est Closured pour vous this contexte de la fonction. Il peut également fermer les paramètres, consultez le documentation.

Pour moi, Function.bind() est la meilleure fonction qui ait jamais été écrit en JavaScript :)

+0

+1. 'Function.bind' sera une fonctionnalité de langage standard dans une future version de JavaScript. – bobince

+0

Vraiment? Pouvez-vous me lier? –

+0

http://wiki.ecmascript.org/doku.php?id=es3.1:es3.1_proposal_working_draft – bobince

1

gestionnaires DOMEvent sont traditionnellement appelés avec les éléments qu'ils sont enregistrés comme contexte/« ce ». C'est ce que jQuery fait aussi.

La définir la updateHandler dans le constructeur

var MyClass = Class.create({ 
initElements: function(sumEl) { 
     this.sumEl = sumEl; 

     // save this as that so we can access it from the anonymous function 
     var that = this; 
     sumEl.keyup(function() 
     { 
      that.updateSum(); 
     }); 
}, 

updateSum: function() { 
     // does something here 
} 
}); 

option la plus facile pour vous serait d'utiliser la capacité de jQuery pour gérer les données d'événements

var MyClass = Class.create({ 
initElements: function(sumEl) { 
     this.sumEl = sumEl; 
     sumEl.bind("keyup", this, this.updateSumHandler); 
}, 

updateSumHandler: function(event) { 
    // event.data is the initial this 

    // call updateSum with correct context 
    event.data.updateSum.call(event.data); 
}, 

updateSum: function() { 
     // does something here 
} 
}); 

L'autre possibilité est d'utiliser des fermetures Ceci est un exemple de travail que l'une des autres réponses a essayé de faire. Cela fonctionne parce que la fonction anonyme peut toujours accéder aux variables dans la fonction environnante - mais cela ne fonctionne que si la fonction est réellement définie dans la fonction qui a "that" comme variable locale.

Questions connexes