Les fonctions fléchées : écrire moins, garder le contrôle
Écrire une fonction fléchée, la raccourcir sans perdre en lisibilité, et comprendre pourquoi elle ne convient pas comme méthode d’objet à cause de la manière dont elle traite this.
Où en êtes-vous avec cette notion ?
Une indication personnelle, enregistrée uniquement dans ce navigateur.
À lire ensuite
Le format café
L’essentiel à comprendre, le temps d’un café.
Envie de creuser ? Un cours plus complet vous attend juste après, à déplier sans quitter cette page.
Ce que vous allez comprendre
Une fonction fléchée n’est pas seulement une écriture plus courte. Elle traite aussi this autrement qu’une fonction classique. Ces deux points expliquent presque tous ses usages.
Une même fonction, trois écritures
// Console du navigateur ou Node.js : les trois donnent 5 pour (2, 3).
function additionClassique(a, b) {
return a + b;
}
const additionFlechee = (a, b) => {
return a + b;
};
const additionCourte = (a, b) => a + b;
Lorsque le corps se limite à un return, les accolades et le mot return peuvent disparaître : la valeur de l’expression est renvoyée directement.
function addition(a, b) { return a + b; }
↓
const addition = (a, b) => { return a + b; };
↓
const addition = (a, b) => a + b;
Pourquoi vous en voyez partout
Ces écritures courtes servent surtout à passer une petite fonction à une autre fonction.
const utilisateurs = [
{ nom: 'Alice', actif: true },
{ nom: 'Bob', actif: false },
];
const actifs = utilisateurs.filter((utilisateur) => utilisateur.actif);
// [ { nom: 'Alice', actif: true } ]
La ligne se lit presque comme une phrase : « garde les utilisateurs dont actif est vrai ». Vous retrouverez la même forme avec map(), find(), reduce() ou forEach().
La subtilité qui compte : this
Une fonction fléchée n’a pas son propre this : elle reprend celui de l’endroit où elle a été écrite. Placée directement dans un objet littéral, elle ne désigne donc pas cet objet.
const utilisateur = {
nom: 'Jean',
afficherNom: () => console.log(this?.nom), // ne lit pas utilisateur.nom
afficherNomCorrect() {
console.log(this.nom); // 'Jean'
},
};
Pour une méthode, préférez la syntaxe abrégée afficherNomCorrect() { … } : this désigne alors l’objet sur lequel la méthode est appelée. La flèche redevient le bon choix à l’intérieur d’une méthode, pour un rappel qui doit conserver le this environnant.
Fiche mémo
| Besoin | Écriture conseillée |
|---|---|
| Petite fonction passée en argument | (x) => x * 2 |
| Méthode d’objet ou de classe | maMethode() { … } |
| Rappel écrit dans une méthode | fonction fléchée |
L’idée à emporter : la flèche raccourcit l’écriture et reprend le this du contexte où elle est écrite ; ce second effet est celui qui décide vraiment de son usage.
Et si on allait plus loin ?
Le café vous a donné les repères. Prenez maintenant le temps de comprendre les mécanismes et de pratiquer, si vous le souhaitez.
Aller plus loinChoisir entre la flèche et le mot function sans se tromper sur thisDévelopper le coursReplier le cours
Ce que vous saurez faire
Écrire une fonction fléchée sans piège de syntaxe, expliquer d’où vient son this, et choisir en connaissance de cause entre la flèche et function. Tous les exemples se lisent dans la console du navigateur ou avec Node.js ; aucun serveur ni installation particulière.
1. Les formes d’écriture, et le piège des accolades
// Node.js ou console du navigateur.
const carre = (x) => x * x;
const direBonjour = () => 'Bonjour';
const enObjetFaux = (nom) => { nom };
const enObjet = (nom) => ({ nom });
console.log(carre(4)); // 16
console.log(direBonjour()); // 'Bonjour'
console.log(enObjetFaux('Jean')); // undefined
console.log(enObjet('Jean')); // { nom: 'Jean' }
Les accolades sont ambiguës : après une flèche, elles délimitent un bloc d’instructions, pas un objet littéral. { nom } est donc lu comme un corps de fonction contenant l’expression nom, sans return : la fonction renvoie undefined. Les parenthèses lèvent l’ambiguïté.
Les parenthèses autour d’un paramètre unique sont facultatives en JavaScript, mais elles redeviennent obligatoires dès qu’il y a une valeur par défaut, un paramètre du reste, une décomposition, ou une annotation de type en TypeScript. Les garder systématiquement évite d’y penser.
Référence : fonctions fléchées.
2. this : ce que la flèche capture réellement
Pour une fonction classique, this dépend de la manière dont on l’appelle. Pour une fonction fléchée, il n’existe pas : le moteur va le chercher dans la portée englobante, comme n’importe quelle autre variable.
Or un objet littéral ne crée pas de portée. Une flèche écrite directement dans un objet, au niveau supérieur d’un fichier, capture donc le this de ce niveau supérieur — dont la valeur dépend du contexte d’exécution :
| Contexte d’exécution | this au niveau supérieur |
|---|---|
Module ES (type="module", fichier .mjs) | undefined |
| Script classique de navigateur | l’objet global (window) |
| Module CommonJS de Node.js | module.exports, un objet vide |
const utilisateur = {
nom: 'Jean',
parFleche: () => this?.nom,
parMethode() {
return this.nom;
},
};
console.log(utilisateur.parMethode()); // 'Jean'
console.log(utilisateur.parFleche()); // undefined dans les trois contextes
Il ne s’agit donc pas d’une valeur unique et universelle. Ce qui est constant, c’est l’absence de this propre à la flèche, pas ce que this vaut. Le ?. est ici indispensable : dans un module ES, this vaut undefined et this.nom lèverait une TypeError.
Le mode strict change lui aussi le résultat, notamment quand on détache une méthode :
const afficher = utilisateur.parMethode;
afficher(); // mode strict : TypeError. Mode non strict : undefined.
En mode strict — celui des modules ES et des classes — this vaut undefined dans un appel sans receveur. En mode non strict, il vaut l’objet global, et la lecture renvoie simplement undefined sans erreur.
Référence : l’opérateur this.
3. Là où la flèche est exactement le bon outil
const panier = {
nom: 'Panier',
articles: ['pomme', 'poire'],
lister() {
return this.articles.map((article) => `${this.nom} : ${article}`);
},
};
console.log(panier.lister());
// [ 'Panier : pomme', 'Panier : poire' ]
Ici la flèche est écrite à l’intérieur de lister(). Elle reprend donc le this de cet appel, c’est-à-dire panier. Avec function (article) { … }, this serait undefined dans un module et l’accès à this.nom lèverait une erreur.
Attention au cas symétrique : dans un gestionnaire passé à addEventListener, une fonction classique reçoit l’élément écouté comme this, une fonction fléchée non. Utilisez event.currentTarget, qui fonctionne dans les deux cas.
Pièges et limites
- Pas d’objet
arguments. Une flèche n’en crée pas ; elle verrait celui de la fonction englobante. Utilisez un paramètre du reste :(...args) => args.length. - Pas utilisable avec
new. Une flèche n’est pas un constructeur et n’a pas deprototype;new maFleche()lève uneTypeError. - Pas de remontée de déclaration.
function estMajeur() {}est utilisable avant sa ligne d’écriture ;const estMajeur = …ne l’est pas, à cause de la zone morte temporelle. - Méthode de classe écrite en champ fléché.
clic = () => {}fige lethisde l’instance, ce qui est pratique, mais crée une fonction par instance au lieu d’une seule sur le prototype. - Lisibilité. Enchaîner
a => b => c => …reste valide mais devient vite illisible ; nommer les étapes est souvent préférable.
À vous de jouer
Voici une fonction classique :
function estMajeur(age) {
return age >= 18;
}
- Réécrivez-la en fonction fléchée, dans sa version la plus courte.
- Prédisez ce qu’affichent
estMajeur(18)puisestMajeur(17). - Que se passe-t-il si vous appelez la version fléchée avant la ligne qui la déclare ?
Correction commentée
// Node.js ou console du navigateur.
const estMajeur = (age) => age >= 18;
console.log(estMajeur(18)); // true
console.log(estMajeur(17)); // false
Deux transformations se sont enchaînées. D’abord, function estMajeur(age) { … } devient une expression rangée dans une constante : const estMajeur = (age) => { return age >= 18; };. Ensuite, le corps ne contenant qu’un return, les accolades et le mot return disparaissent : l’expression age >= 18 devient directement la valeur renvoyée.
L’opérateur >= produit déjà un booléen ; écrire ? true : false serait redondant. Et comme cette fonction n’utilise pas this, la flèche ne présente ici aucun risque : c’est exactement le cas où elle est préférable.
Pour la troisième question : appeler estMajeur(18) avant la ligne const estMajeur = … lève une ReferenceError. La constante est bien réservée dans la portée, mais reste inaccessible jusqu’à son initialisation ; c’est la zone morte temporelle. Une déclaration function, elle, aurait fonctionné. La différence est réelle et n’a rien à voir avec this.
En TypeScript, la même fonction s’annote ainsi — et les parenthèses autour du paramètre deviennent alors obligatoires :
const estMajeur = (age: number): boolean => age >= 18;
Vous pouvez aussi vous arrêter ici. L’approfondissement est facultatif.
Les repères Cours Café
Pour aller à la source
Documentation de référence. Vérification éditoriale encore à effectuer.
Gardez une trace de cette idée.
Favoris, notes et progression seront disponibles après connexion du stockage distant.