Il était une fois un développeur JavaScript qui pensait maîtriser son sujet. Il avait réalisé une fonctionnalité qui utilisait this. Voici le code qu'il a écrit :
function User(name) {
this.name = name;
// Une méthode qui utilise "this"
this.sayHello = function () {
console.log(`Bonjour, je suis ${this.name}`);
};
setTimeout(function () {
updateState(this.name);
}, 1000);
}
const user = new User("Jean-Michel");
user.sayHello(); // OK : Bonjour, je suis Jean-Michel
Dans le setTimeout, le this.name sera toujours undefined, à cause d'un problème assez simple de scope.
Bon, il s'agit d'un exemple assez simple, mais pourtant, ce type d'erreur est assez courant, this a toujours provoqué des problèmes de développement.
Le problème de This
Le mot-clé this est un mot-clé spécial en JavaScript qui est largement utilisé dans les fonctions, les méthodes et les constructeurs.
This fait référence au contexte d'appel en JavaScript, c'est ici que le principal point de blocage apparaît.
JavaScript permet d'utiliser des callbacks, des appels de fonctions dans les fonctions.
Le problème est que le this dans une fonction callback n'est pas le même que le this de la fonction parente.
Ce problème existe aussi dans les class. Lorsque l'on utilise une méthode de class dans un callback (un middleware Express par exemple), le contexte de la class ne sera pas partagé.
Les solutions
Bon, comment aider notre développeur ?
Bind
La méthode bind() crée une nouvelle fonction qui, lorsqu'elle est appelée, a this défini à la valeur passée comme premier argument.
setTimeout(function () {
updateState(this.name);
}.bind(this), 1000);
Avec bind, il est possible de passer n'importe quel contexte, ce qui permet la composition de fonctions.
Arrow function
Les fonctions fléchées ne créent pas leur propre this, elles héritent du this de la fonction parente.
setTimeout(() => {
updateState(this.name);
}, 1000);
Pour conclure, si vous constatez que this est undefined, pensez à regarder le scope de ce this. Est-ce qu'il est appelé correctement dans votre code ?