Pourquoi this fonctionne correctement dans une fonction fléchée ?

Un des bénéfices des fonctions fléchées est que this est bindé au contexte dans lequel la fonction est définie, et non au this de la fonction elle-même. Qu’est-ce que ça veut dire exactement ?

RAPPEL : Les fonctions fléchées sont une syntaxe raccourcie pour les expressions de fonction.

Comportement de this AVANT les fonctions fléchées (= dans les expressions de fonction)

Avant les fonctions fléchées, chaque nouvelle expression de fonction définissait son propre this, ce qui était souvent source de problèmes.

Prenons le code JavaScript (ES6) suivant, qui n’utilise PAS de fonction fléchée dans le forEach :

class MyClass {

  logNames() {
    const names = ['Pierre', 'Paul', 'Jacques'];
    names.forEach(function (name) {  // Expression de fonction classique
      this.log(name);
    });
  }

  log(value) {
    console.log(value);
  }
}

const c = new MyClass();
c.logNames();

L’appel à this.log(name) se trouve à l’intérieur d’une expression de fonction classique. A l’exécution, cette ligne déclenchera l’erreur “Cannot read property ‘log’ of undefined”. En effet, dans l’expression de fonction, this ne référence plus l’instance de la classe mais le this de la fonction…

Une solution traditionnellement utilisée en JavaScript était de copier une référence à this avant d’entrer dans l’expression de fonction et d’utiliser la copie à l’intérieur de la fonction (le fameux var that = this).

Avec cette correction, la méthode logNames() devient :

class MyClass {
  logNames() {
    const names = ['Pierre', 'Paul', 'Jacques'];
    const that = this;  // On copie `this` tant qu'il a encore la bonne valeur
    names.forEach(function (name) {
      that.log(name);   // On utilise la copie de `this`
    });
  }
  
  log(value) {
    console.log(value);
  }
}

À présent le code fonctionne, mais ça n’est ni très pratique ni très élégant.

Comportement de this AVEC les fonctions fléchées

Dans le corps d’une fonction fléchée, this n’est pas bindé à la fonction elle-même, mais au contexte dans lequel la fonction est définie.

Si l’on reprend l’exemple précédent, this pointera donc sur l’instance de MyClass et le code aura le comportement attendu à l’exécution.

class MyClass {
  logNames() {
    const names = ['Pierre', 'Paul', 'Jacques'];
    names.forEach((name) => {  // Notez l'utilisation d'une fonction fléchée
      this.log(name);          // Ce `this` pointe bien sur l'instance de classe
    });
  }

  log(value) {
    console.log(value);
  }
}

Il est donc conseillé d’utiliser les fonctions fléchées plutôt que les expressions de fonction, surtout à l’intérieur d’une classe ou d’une fonction constructeur.

Un autre bénéfice de ces fonctions est leur syntaxe plus légère et plus élégante.



Ressources supplémentaires

Informations

Tags : javascript

Dernière mise à jour :

Auteur : AngularChef

Qualité : Bonne