Fonctions fléchées JavaScript
Apprenez en profondeur le fonctionnement des fonctions fléchées JavaScript : this lexical, pas d'arguments propres ni de super, pourquoi elles ne peuvent pas être des constructeurs.
Introduction aux fonctions fléchées JavaScript
Les fonctions fléchées, introduites dans ES6 (ECMAScript 2015), sont désormais une fonctionnalité clé de JavaScript, offrant une façon plus concise d'écrire des expressions de fonction. Elles sont particulièrement appréciées car elles simplifient le code et aident à résoudre les problèmes courants liés au mot-clé this.
Cette page va au-delà de la syntaxe (couverte dans Les fonctions fléchées, les bases) et explore pourquoi les fonctions fléchées se comportent comme elles le font. En résumé, une fonction fléchée n'a aucune liaison propre. Elle n'obtient pas son propre this, ses propres arguments, son propre super, ni de méthode [[Construct]]. Chaque fois que vous référencez l'un de ces éléments dans une fonction fléchée, JavaScript les recherche dans la portée englobante (lexicale), exactement comme il le ferait pour n'importe quelle variable ordinaire. Pratiquement toutes les particularités et tous les avantages des fonctions fléchées découlent de cette unique règle.
Définir des fonctions fléchées
Les fonctions fléchées permettent une syntaxe plus courte par rapport aux expressions de fonction traditionnelles. Voici une comparaison de base pour l'illustrer :
La version avec fonction fléchée est non seulement plus courte, mais elle élimine également le besoin du mot-clé function et des accolades lorsqu'il n'y a qu'une seule expression.
Variantes de syntaxe
Les fonctions fléchées peuvent être écrites sous différentes formes selon le nombre de paramètres et la complexité du corps de la fonction :
- Aucun paramètre : utilisez des parenthèses vides :
- Un seul paramètre : les parenthèses sont facultatives :
- Plusieurs paramètres : les parenthèses sont obligatoires :
- Plusieurs lignes : utilisez des accolades et un
returnexplicite (si la fonction retourne une valeur) :
Les fonctions fléchées n'ont pas leur propre this
La propriété la plus importante des fonctions fléchées est qu'elles n'obtiennent pas leur propre this. Une fonction ordinaire détermine son this au moment de l'appel, selon la façon dont elle est appelée (voir Méthodes d'objet, « this »). Une fonction fléchée ignore tout cela et lit this depuis la portée où elle a été définie — on appelle cela le this lexical.
C'est exactement ce que vous souhaitez lorsqu'une fonction fléchée s'exécute en tant que rappel. Une méthode qui perd son this à l'intérieur d'un rappel ordinaire le conserve à l'intérieur d'une fonction fléchée :
Remplacez la fonction fléchée par une function(member) { ... } ordinaire et this à l'intérieur de forEach devient undefined, provoquant l'erreur Cannot read properties of undefined. Avant les fonctions fléchées, les développeurs contournaient ce problème avec const self = this; ou .bind(this) — voir Liaison de fonction. Les fonctions fléchées éliminent le besoin de ces astuces.
La même règle lexicale résout le problème classique des minuteries, où un rappel s'exécute de manière détachée de son objet :
Parce que this est fixé lexicalement, vous ne pouvez pas le modifier. Appeler .call(), .apply() ou .bind() sur une fonction fléchée n'a aucun effet sur this — la liaison est ignorée :
Les fonctions fléchées n'ont pas d'arguments
Les fonctions fléchées n'ont pas non plus leur propre objet arguments. Référencer arguments à l'intérieur d'une fonction fléchée remonte vers la fonction englobante — ce qui est pratique pour les wrappers et les décorateurs :
Si vous avez réellement besoin des arguments de la fonction fléchée elle-même, utilisez les paramètres rest (...args), qui fonctionnent partout :
Les fonctions fléchées ne peuvent pas être des constructeurs
Puisqu'une fonction fléchée n'a pas de méthode interne [[Construct]] ni de propriété prototype, vous ne pouvez pas l'utiliser avec l'opérateur new :
Pour la même raison, les fonctions fléchées ne peuvent pas référencer super pour accéder à une classe parente, et ne sont donc jamais utilisées comme constructeurs de classe ou méthodes de classe qui dépendent de super.
Quand ne pas utiliser les fonctions fléchées
Le this lexical est idéal dans les rappels, mais inapproprié dans certains cas courants. Préférez une fonction ordinaire lorsque la fonction a besoin de son propre this dynamique.
Méthodes d'objet
Lorsqu'une fonction est une méthode d'un objet, vous souhaitez généralement que this pointe vers cet objet. Une fonction fléchée prend this depuis la portée externe (souvent la portée du module ou globale) et ne verra donc pas les propriétés propres de l'objet :
Utilisez la syntaxe abrégée de méthode ordinaire (ou une expression function) pour les méthodes d'objet. Consultez Méthodes d'objet, « this » pour une vue d'ensemble complète.
Méthodes de prototype et constructeurs
Étant donné que les fonctions fléchées ne peuvent pas être des constructeurs et n'ont pas leur propre this, elles ne peuvent pas définir des méthodes de prototype ni servir de fonctions constructeurs. Les méthodes ajoutées à un prototype doivent être des fonctions ordinaires pour que chaque instance résolve this vers elle-même.
Gestionnaires d'événements DOM (dans le navigateur)
Lorsque vous attachez un gestionnaire avec addEventListener, le navigateur l'appelle avec this défini sur l'élément ayant reçu l'événement. Une fonction fléchée ignore cela et conserve le this externe, donc utilisez une fonction ordinaire si vous avez besoin que this soit l'élément (vous pouvez toujours utiliser event.currentTarget dans tous les cas).
Techniques avancées
Retourner des littéraux d'objet
Pour retourner un littéral d'objet depuis une fonction fléchée, entourez l'objet de parenthèses :
IIFE avec des fonctions fléchées
Les fonctions fléchées peuvent être utilisées pour les expressions de fonction immédiatement invoquées (IIFE) :
Résumé
Les fonctions fléchées se comprennent mieux par ce qu'elles n'ont pas. Elles ont :
- Pas de
thispropre — il est pris depuis la portée englobante (thislexical), et.call/.apply/.bindne peuvent pas le modifier. Idéal pour les rappels, inapproprié pour les méthodes d'objet. - Pas d'
argumentspropres — utilisez les paramètres rest (...args) si vous en avez besoin. - Pas de
super— elles ne peuvent donc pas être des méthodes de classe appelant un parent. - Pas de
[[Construct]]ni deprototype— elles ne peuvent donc pas être utilisées avecnewni comme méthodes de prototype.
Utilisez les fonctions fléchées pour les rappels courts et toute fonction devant conserver son this externe. Utilisez des fonctions ordinaires pour les méthodes d'objet, les méthodes de prototype, les constructeurs et les gestionnaires DOM qui ont besoin d'un this dynamique.
Chapitres associés
- Les fonctions fléchées, les bases
- Méthodes d'objet, « this »
- Liaison de fonction
- Constructeur, opérateur « new »
- Paramètres rest et syntaxe de décomposition