Image d'illustration -JavaScript ES6 : Les fonctions fléchées

Les fonctions fléchées (arrow functions) sont à mon sens une des choses qui apportent le plus grand changement en ES6 et sont très utilisées actuellement. Elles arrivent d'ailleurs en PHP avec la version 7.4 ! Elles diffèrent très légèrement des fonctions régulières et voici comment.

Les fonctions fléchées ont été introduites en JavaScript avec la version ES6/ECMAScript 2015 et ont changé pour toujours le look d'un code JS et la façon dont il fonctionne.
Cela a été tellement bienvenu qu'il se fait désormais rare de voir un code utiliser le mot function dans du code moderne. Mais attention, il a toujours son utilité !

Visuellement c'est un changement assez simple à comprendre qui vous permet de faire une syntaxe plus courte pour déclarer une fonction, on passe alors de :

const myFunction = function() {
  //...
};

À :

const myFunction = () => {
  //...
};


Si le corps de la fonction ne contient qu'une instruction, vous pouvez omettre les accolades et écrire le code sur une seule ligne :

const myFunction = () => doSomething();


Les paramètres sont passés comme d'habitude dans les parenthèses :

const myFunction = (param1, param2) => doSomething(param1, param2);


Si vous n'avez qu'un seul paramètre, vous pouvez omettre les parenthèses :

const myFunction = param => doSomething(param);


Grâce à cette syntaxe courte, les fonctions fléchées vous encouragent à utiliser de petites fonctions et ainsi améliorer la lisibilité de votre code en le découpant.

Retour implicite

 

Les fonctions fléchées vous permettent d'avoir un retour (return) implicite : les valeurs sont retournées sans l'utilisation du mot-clé return.


Cela fonctionne simplement lorsque vous n'avez qu'une ligne d'instruction dans le corps de votre fonction :

const myFunction = () => 'test';

console.log(myFunction()); // affiche dans la console 'test'


Voici un autre exemple vous montrant une petite spécificité lorsque vous retournez un objet. N'oubliez pas à ce moment-là de mettre des parenthèses autour des accolades de l'objet afin que celles-ci soient bien considérées comme telles et non des accolades entourant un bloc d'instructions :

const myFunction = () => ({ value: 'test' });

console.log(myFunction()); //affiche dans la console : {value: 'test'}

 

Le fonctionnement de this dans les fonctions fléchées
 

this est un concept qui n'est pas évident à appréhender car sa valeur varie souvent en fonction du contexte et du mode de JavaScript (mode strict ou non).

Il est important de clarifier ce concept car les fonctions fléchées se comportent très différemment des fonctions régulières à ce sujet.

Lorsqu'une fonction est définie en tant que méthode d'un objet, dans une fonction régulière this se réfère à l'objet et vous pouvez donc faire :

const car = {
  model: 'Fiesta',
  manufacturer: 'Ford',
  fullName: function() {
    return `${this.manufacturer} ${this.model}`;
  }
};


Appeler car.fullName() retournera "Ford Fiesta".

La portée de this dans les fonctions fléchées est héritée du contexte d'exécution. Une fonction fléchée ne lie pas this du tout (elle ne bind pas de valeur). Sa valeur sera donc recherchée dans la pile d'appel (call stack). Ainsi dans le code ci-dessous, car.fullName() ne fonctionnera pas et renverra la chaîne "undefined undefined".

const car = {
  model: 'Fiesta',
  manufacturer: 'Ford',
  fullName: () => `${this.manufacturer} ${this.model}`
};


Pour cette raison, les fonctions fléchées ne sont pas faites pour faire des méthodes d'objet.

Les fonctions fléchées ne peuvent pas être utilisées comme constructeurs également. Si vous faites cela, l'instanciation de l'objet lèvera une TypeError.

Voilà donc pourquoi le mot-clé function a toujours son utilité : dans le cadre d'un contexte dynamique.

Enfin, cela pose également problème lorsque l'on parle de gestionnaires d'évènements. Les écouteurs d'évènements DOM définissent la valeur de this à l'élément cible de l'évènement (target), et si vous comptez sur this dans un gestionnaire d'évènement, une fonction régulière est nécessaire :

const link = document.querySelector('#link');

link.addEventListener('click', () => {
  // this === window
});

 

const link = document.querySelector('#link');

link.addEventListener('click', function() {
  // this === link
});


Mais n'oubliez pas que vous restez dans un gestionnaire d'évènement et disposez des informations de l'évènement en paramètre et donc de la cible :

const link = document.querySelector('#link');

link.addEventListener('click', (e) => {
  // this === window
  // MAIS
  // e.target === link !
});

 


4