L'utilisation de méthodes d'instance en tant que rappels pour les gestionnaires d'événements modifie la portée de this
de "Mon instance" à "Tout ce qui vient d'appeler le rappel". Donc, mon code ressemble à ceci
function MyObject() {
this.doSomething = function() {
...
}
var self = this
$('#foobar').bind('click', function(){
self.doSomethng()
// this.doSomething() would not work here
})
}
Cela fonctionne, mais est-ce la meilleure façon de le faire? Cela me semble étrange.
Cette question n'est pas spécifique à jQuery, mais spécifique à JavaScript en général. Le principal problème est de savoir "canaliser" une variable dans les fonctions intégrées. Voici l'exemple:
var abc = 1; // we want to use this variable in embedded functions
function xyz(){
console.log(abc); // it is available here!
function qwe(){
console.log(abc); // it is available here too!
}
...
};
Cette technique repose sur l'utilisation d'une fermeture. Mais cela ne fonctionne pas avec this
, car this
est une pseudo-variable qui peut changer de portée de manière dynamique:
// we want to use "this" variable in embedded functions
function xyz(){
// "this" is different here!
console.log(this); // not what we wanted!
function qwe(){
// "this" is different here too!
console.log(this); // not what we wanted!
}
...
};
Que pouvons-nous faire? Attribuez-le à une variable et utilisez-le via l'alias:
var abc = this; // we want to use this variable in embedded functions
function xyz(){
// "this" is different here! --- but we don't care!
console.log(abc); // now it is the right object!
function qwe(){
// "this" is different here too! --- but we don't care!
console.log(abc); // it is the right object here too!
}
...
};
this
n'est pas unique à cet égard: arguments
est l'autre pseudo-variable qui devrait être traitée de la même manière - par aliasing.
Oui, cela semble être une norme commune. Certains codeurs utilisent eux-mêmes, d'autres m'utilisent. Il est utilisé comme référence à l'objet "réel" par opposition à l'événement.
C'est quelque chose qui m'a pris un peu de temps à obtenir vraiment, ça a l'air bizarre au début.
Je le fais habituellement tout en haut de mon objet (excusez mon code de démonstration - c'est plus conceptuel qu'autre chose et ce n'est pas une leçon sur l'excellente technique de codage):
function MyObject(){
var me = this;
//Events
Click = onClick; //Allows user to override onClick event with their own
//Event Handlers
onClick = function(args){
me.MyProperty = args; //Reference me, referencing this refers to onClick
...
//Do other stuff
}
}
Si vous effectuez ES2015 ou le script de type et ES5, vous pouvez utiliser des fonctions de flèche dans votre code. Vous ne rencontrez pas cette erreur et cela fait référence à l'étendue souhaitée de votre instance.
this.name = 'test'
myObject.doSomething(data => {
console.log(this.name) // this should print out 'test'
});
var functionX = function() {
var self = this;
var functionY = function(y) {
// If we call "this" in here, we get a reference to functionY,
// but if we call "self" (defined earlier), we get a reference to function X.
}
}
edit: malgré, les fonctions imbriquées dans un objet prennent l'objet fenêtre globale plutôt que l'objet environnant.
Une solution à ce problème consiste à lier tout votre rappel à votre objet avec la méthode bind
de javascript.
Vous pouvez le faire avec une méthode nommée,
function MyNamedMethod() {
// You can now call methods on "this" here
}
doCallBack(MyNamedMethod.bind(this));
Ou avec un rappel anonyme
doCallBack(function () {
// You can now call methods on "this" here
}.bind(this));
Faire cela au lieu de recourir à var self = this
Montre que la liaison de this
se comporte en javascript et ne repose pas sur une référence de fermeture.
En outre, l'opérateur de flèche en gras dans ES6 est fondamentalement le même qu'un appel .bind(this)
sur une fonction anonyme:
doCallback( () => {
// You can reference "this" here now
});
Je n'ai pas utilisé jQuery, mais dans une bibliothèque telle que Prototype, vous pouvez lier des fonctions à une portée spécifique. Donc, dans cet esprit, votre code ressemblerait à ceci:
$('#foobar').ready('click', this.doSomething.bind(this));
La méthode bind renvoie une nouvelle fonction qui appelle la méthode d'origine avec l'étendue que vous avez spécifiée.
Ajoutez simplement à cela que dans ES6 à cause de fonctions de flèche vous ne devriez pas avoir à le faire car ils capturent la valeur this
.
Je pense que cela dépend de ce que vous allez faire dans votre fonction doSomething
. Si vous souhaitez accéder à MyObject
propriétés à l'aide de ce mot clé, vous devez l'utiliser. Mais je pense que le fragment de code suivant fonctionnera aussi si vous ne faites pas de choses spéciales en utilisant les propriétés object(MyObject)
.
function doSomething(){
.........
}
$("#foobar").ready('click', function(){
});