À propos de ce cours
Cette leçon présente les fonctions fléchées, apparues avec ES6 : leurs cinq formes d'écriture, la différence entre corps concis (retour implicite) et corps en bloc, et les deux erreurs les plus fréquentes, l'oubli de return et l'objet renvoyé sans parenthèses. Vous comprendrez pourquoi une fonction fléchée garde le this du code qui l'entoure, ce qui en fait le meilleur choix pour les callbacks de map, filter, forEach ou setTimeout écrits dans une classe. Vous verrez aussi leurs limites : pas d'arguments, pas de new, et pourquoi on ne les utilise pas pour les méthodes d'un objet. Des exemples tirés d'un composant Angular, des schémas et cinq activités pratiques accompagnent chaque notion.
-
Objectifs
- Écrire une fonction fléchée sous ses différentes formes
- Distinguer le corps concis (retour implicite) et le corps en bloc
- Comprendre le comportement de
thisdans une fonction fléchée - Connaître les limites des fonctions fléchées : pas de
arguments, pas denew, pas de méthode d'objet utilisantthis - Utiliser les fonctions fléchées comme callbacks et écrire des fonctions qui renvoient des fonctions
- Reconnaître et utiliser les fonctions fléchées dans un composant Angular
-
Présentation
- Une fonction fléchée (arrow function) est une façon courte d'écrire une fonction, apparue avec ES6 (ES2015). Elle doit son nom à la flèche
=>qui sépare les paramètres du corps de la fonction. - Elle apporte deux avantages :
- une syntaxe concise, très lisible pour les petites fonctions passées en paramètre (
map,filter,setTimeout…) ; - un
thislexical: la fonction fléchée n'a pas son proprethis, elle utilise celui du code qui l'entoure. Elle supprime ainsi l'une des plus grandes sources de bugs de JavaScript.
- une syntaxe concise, très lisible pour les petites fonctions passées en paramètre (
- Dans un projet Angular, les fonctions fléchées sont partout : traitement des listes, minuteries, réponses du client HTTP, signals calculés…
- Une fonction fléchée (arrow function) est une façon courte d'écrire une fonction, apparue avec ES6 (ES2015). Elle doit son nom à la flèche

-
Trois façons d'écrire une fonction
- La même fonction peut s'écrire de trois manières en JavaScript :
// 1. Déclaration de fonction
function prixTTC1(ht) {
return ht * 1.19;
}
// 2. Expression de fonction (fonction anonyme rangée dans une constante)
const prixTTC2 = function (ht) {
return ht * 1.19;
};
// 3. Fonction fléchée
const prixTTC3 = (ht) => ht * 1.19;
console.log(prixTTC1(100), prixTTC2(100), prixTTC3(100)); // 119 119 119
- Une fonction fléchée est toujours anonyme: pour la réutiliser, on la range dans une constante (
const), ou on la passe directement en paramètre à une autre fonction. - Attention : contrairement à une déclaration de fonction, une fonction fléchée rangée dans une
constn'est pas remontée (hoisting) : on ne peut pas l'appeler avant sa ligne de définition (voir let, const et portée des variables).
test(); // ReferenceError: Cannot access 'test' before initialization
const test = () => 1;
-
Les différentes formes
- La syntaxe s'adapte au nombre de paramètres et à la longueur du corps :

const direBonjour = () => 'Bonjour'; // aucun paramètre : () obligatoires
const doubler = n => n * 2; // un seul paramètre : () facultatives
const additionner = (a, b) => a + b; // plusieurs paramètres : () obligatoires
const saluer = (nom = 'stagiaire') => `Bonjour ${nom}`; // paramètre par défaut
const mention = (moyenne) => { // plusieurs instructions : bloc + return
if (moyenne >= 16) return 'Très bien';
if (moyenne >= 10) return 'Admis';
return 'Ajourné';
};
const creerStagiaire = (nom, groupe) => ({ nom, groupe, actif: true }); // objet : ( )
console.log(direBonjour(), doubler(21), additionner(2, 3), saluer(), mention(17));
// Bonjour 42 5 Bonjour stagiaire Très bien
console.log(creerStagiaire('Amira', 'DEV1'));
// { nom: 'Amira', groupe: 'DEV1', actif: true }
- Conseil : le formateur Prettier, installé avec VS Code, ajoute automatiquement les parenthèses autour d'un paramètre unique :
(n) => n * 2. Cette écriture est plus uniforme ; c'est celle utilisée dans la suite du cours.
Corps concis et corps en bloc
- Corps concis: une seule expression, sans accolades. Sa valeur est renvoyée automatiquement (retour implicite).
- Corps en bloc: des accolades
{ }contenant des instructions. Rien n'est renvoyé sans le mot-cléreturn. - Deux erreurs sont très fréquentes :
// Erreur 1 : accolades sans return → la fonction renvoie undefined
const tripler = (n) => { n * 3; };
console.log(tripler(5)); // undefined
// Erreur 2 : objet renvoyé sans parenthèses
const creer = (nom) => { nom: nom };
console.log(creer('Sami')); // undefined : { } est lu comme un bloc, "nom:" comme une étiquette
const creer2 = (nom, groupe) => { nom: nom, groupe: groupe };
// SyntaxError: Unexpected token ':'
// Corrections
const triplerOk = (n) => n * 3; // ou { return n * 3; }
const creerOk = (nom, groupe) => ({ nom, groupe });
-
this dans une fonction fléchée
- Dans une fonction classique,
thisdépend de la façon dont la fonction est appelée. Quand on passe une fonction classique àforEach, àsetTimeoutou à un autre code, elle perd lethisde l'objet. - Une fonction fléchée n'a pas de
this: elle utilise celui de l'endroit où elle est écrite. On dit que sonthisest lexical.
- Dans une fonction classique,

class Formateur {
constructor(nom, groupes) {
this.nom = nom;
this.groupes = groupes;
}
afficherClassique() {
this.groupes.forEach(function (g) {
console.log(`${this.nom} enseigne en ${g}`); // this vaut undefined ici
});
}
afficherFlechee() {
this.groupes.forEach((g) => console.log(`${this.nom} enseigne en ${g}`));
}
}
const ali = new Formateur('Ali', ['DEV1', 'DEV2']);
ali.afficherFlechee();
// Ali enseigne en DEV1
// Ali enseigne en DEV2
ali.afficherClassique();
// TypeError: Cannot read properties of undefined (reading 'nom')
- Avant ES6, on contournait le problème en stockant
thisdans une variable (var self = this;) ou avec.bind(this). Les fonctions fléchées rendent ces astuces inutiles. - Exemple : une minuterie dans une classe
class Chrono {
secondes = 0;
demarrer() {
const id = setInterval(() => {
this.secondes++; // this = l'objet Chrono
console.log(`Chrono : ${this.secondes} s`);
if (this.secondes === 3) clearInterval(id);
}, 1000);
}
}
new Chrono().demarrer();
// Chrono : 1 s
// Chrono : 2 s
// Chrono : 3 s
-
Une méthode passée en paramètre perd son this
- Le problème existe aussi quand on passe une méthode à une autre fonction : elle est alors appelée seule, sans son objet.
- Une solution consiste à déclarer la méthode comme une propriété contenant une fonction fléchée: son
thisreste attaché à l'objet.
class Compteur {
valeur = 0;
incrementer() { // méthode classique
this.valeur++;
return this.valeur;
}
incrementerFlechee = () => { // propriété contenant une fonction fléchée
this.valeur++;
return this.valeur;
};
}
const c = new Compteur();
const ref1 = c.incrementer;
ref1(); // TypeError: Cannot read properties of undefined (reading 'valeur')
const ref2 = c.incrementerFlechee;
console.log(ref2(), ref2()); // 1 2
setTimeout(c.incrementerFlechee, 0); // fonctionne aussi
-
Ce que les fonctions fléchées n'ont pas
- Pas de
thispropre: c'est leur force dans les callbacks, mais un défaut pour les méthodes d'un objet.
- Pas de
const groupe = {
nom: 'DEV1',
presenterFlechee: () => `Groupe ${this.nom}`, // this n'est pas l'objet groupe
presenter() { // syntaxe de méthode : correct
return `Groupe ${this.nom}`;
},
};
console.log(groupe.presenterFlechee()); // Groupe undefined
console.log(groupe.presenter()); // Groupe DEV1
- Pas d'objet
arguments: on utilise le paramètre rest...valeurs, qui donne un vrai tableau.
function compterClassique() {
return arguments.length;
}
const compterFlechee = (...valeurs) => valeurs.length;
console.log(compterClassique(1, 2, 3), compterFlechee(1, 2, 3)); // 3 3
- Pas de constructeur: une fonction fléchée ne peut pas être appelée avec
new, et elle n'a pas de propriétéprototype. Pour créer des objets, on utilise une classe.
const Personne = (nom) => {
this.nom = nom;
};
new Personne('Ali'); // TypeError: Personne is not a constructor
- Dans le navigateur, un écouteur d'événement écrit avec une fonction classique reçoit l'élément cliqué dans
this; une fonction fléchée, non. On utilise alors le paramètre de l'événement :
const bouton = document.querySelector('#valider');
bouton.addEventListener('click', function () {
this.classList.add('active'); // this = le bouton
});
bouton.addEventListener('click', (event) => {
event.currentTarget.classList.add('active'); // this n'est pas le bouton : on passe par l'événement
});

-
Les fonctions fléchées comme callbacks
- Un callback (fonction de rappel) est une fonction passée en paramètre à une autre fonction, qui l'appellera au bon moment. C'est l'usage principal des fonctions fléchées.
const stagiaires = [
{ nom: 'Amira', groupe: 'DEV1', moyenne: 15.5 },
{ nom: 'Sami', groupe: 'DEV2', moyenne: 9.75 },
{ nom: 'Yasmine', groupe: 'DEV1', moyenne: 12 },
{ nom: 'Karim', groupe: 'DEV2', moyenne: 17.25 },
];
// Avant ES6
var nomsAdmis = stagiaires
.filter(function (s) { return s.moyenne >= 10; })
.map(function (s) { return s.nom; });
// Avec des fonctions fléchées
const admis = stagiaires
.filter((s) => s.moyenne >= 10)
.map((s) => s.nom);
console.log(admis); // [ 'Amira', 'Yasmine', 'Karim' ]
const moyenneGenerale = stagiaires.reduce((total, s) => total + s.moyenne, 0) / stagiaires.length;
console.log(moyenneGenerale.toFixed(2)); // 13.63
setTimeout(() => console.log('Affiché après 2 secondes'), 2000);
-
Des fonctions qui renvoient des fonctions
- Une fonction fléchée peut renvoyer une autre fonction fléchée. On obtient une fabrique de fonctions, paramétrée une fois puis réutilisée. Grâce à la fermeture, la fonction renvoyée se souvient du paramètre reçu.
const multiplierPar = (facteur) => (n) => n * facteur;
const triple = multiplierPar(3);
console.log(triple(5)); // 15
console.log(multiplierPar(10)(4)); // 40
// Utilisation pratique : une remise réutilisable avec map
const appliquerRemise = (taux) => (prix) => +(prix * (1 - taux)).toFixed(3);
console.log([100, 45.5, 20].map(appliquerRemise(0.1))); // [ 90, 40.95, 18 ]
-
Les fonctions fléchées dans Angular
- Dans un composant Angular, les méthodes s'écrivent avec la syntaxe classique (
supprimer(id) { … }). Les fonctions fléchées servent pour tout ce qu'on passe en paramètre à l'intérieur de ces méthodes : elles conservent lethisdu composant.
- Dans un composant Angular, les méthodes s'écrivent avec la syntaxe classique (
export class ListeFormations {
formations: Formation[] = [
{ id: 1, titre: 'Développement web', placesRestantes: 6 },
{ id: 2, titre: 'Réseaux informatiques', placesRestantes: 0 },
{ id: 3, titre: 'Infographie et design', placesRestantes: 10 },
];
recherche = 'web';
message = '';
get formationsFiltrees(): Formation[] {
return this.formations.filter((f) =>
f.titre.toLowerCase().includes(this.recherche.toLowerCase()),
);
}
get placesTotales(): number {
return this.formations.reduce((total, f) => total + f.placesRestantes, 0);
}
supprimer(id: number): void {
this.formations = this.formations.filter((f) => f.id !== id);
this.message = 'Formation supprimée';
setTimeout(() => (this.message = ''), 3000); // efface le message après 3 s
}
}
- Vous rencontrerez aussi des fonctions fléchées dans les API d'Angular :
computed(() => …)eteffect(() => …)avec les signals, ousubscribe((donnees) => …)avec le client HTTP. Ces notions seront étudiées dans les chapitres suivants. - Dans un template : on n'écrit pas la logique dans le HTML. On appelle une méthode du composant, par exemple
(click)="supprimer(f.id)", et c'est cette méthode qui utilise des fonctions fléchées.
Activité 1 : convertir en fonctions fléchées
- Dans le dossier
rappel-ecmascript(dépôt GitHub), créer le fichier14-conversion.js. Réécrire chaque fonction en fonction fléchée, sous la forme la plus courte possible, puis vérifier le résultat.
function carre(n) {
return n * n;
}
function estMajeur(age) {
return age >= 18;
}
function initiales(prenom, nom) {
return prenom[0] + '.' + nom[0] + '.';
}
function creerProduit(nom, prix) {
return { nom: nom, prix: prix, stock: 0 };
}
function moyenne(notes) {
if (notes.length === 0) {
return 0;
}
var somme = 0;
for (var i = 0; i < notes.length; i++) {
somme += notes[i];
}
return somme / notes.length;
}
console.log(carre(7), estMajeur(17), initiales('Amira', 'Ben Ali'));
console.log(creerProduit('Clavier', 45), moyenne([12, 15, 18]), moyenne([]));
// Résultat attendu :
// 49 false A.B.
// { nom: 'Clavier', prix: 45, stock: 0 } 15 0
- Pour
initiales, utiliser un gabarit`${ }`; pourmoyenne, remplacer la boucle parreduce. Quelle fonction ne peut pas s'écrire avec un corps concis ? Pourquoi ?
Activité 2 : trouver les trois bugs
- Copier ce programme dans
15-bugs.jset l'exécuter. Il contient trois erreurs liées aux fonctions fléchées.
const prixTTC = (ht) => { ht * 1.19; };
const creerFormation = (titre, duree) => { titre: titre, duree: duree };
const groupe = {
nom: 'DEV1',
effectif: 24,
presenter: () => `Groupe ${this.nom} : ${this.effectif} stagiaires`,
};
console.log(prixTTC(100));
console.log(creerFormation('Web', 24));
console.log(groupe.presenter());
- Le programme s'arrête d'abord sur une
SyntaxError: Unexpected token ':'. Quelle ligne est en cause ? La corriger. - Relancer : le programme affiche
undefinedpuisGroupe undefined : undefined stagiaires. Expliquer et corriger les deux autres bugs. - Résultat attendu après correction :
119
{ titre: 'Web', duree: 24 }
Groupe DEV1 : 24 stagiaires
-
Activité 3 : traiter une liste de commandes
- Dans
16-commandes.js, à partir du tableau ci-dessous, écrire chaque traitement en une seule instruction, avec des méthodes de tableaux et des fonctions fléchées. Commencer par une fonction fléchéemontant(c)qui calculeprix × quantité.
- Dans
const commandes = [
{ client: 'Amira', produit: 'Clavier', prix: 45, quantite: 2, payee: true },
{ client: 'Sami', produit: 'Écran', prix: 420, quantite: 1, payee: false },
{ client: 'Yasmine', produit: 'Souris', prix: 20, quantite: 3, payee: true },
{ client: 'Karim', produit: 'Casque', prix: 85, quantite: 1, payee: true },
{ client: 'Amira', produit: 'Câble HDMI', prix: 12.5, quantite: 4, payee: false },
];
- les commandes payées, sous la forme
client : produit(filter+map) ; - le chiffre d'affaires encaissé, c'est-à-dire le total des commandes payées (
reduce) ; - les impayés, sous la forme
client doit montant DT; - les trois produits les plus chers à la commande (
toSorted+slice+map) ; - existe-t-il une commande de plus de 400 DT (
some) ? Toutes les quantités sont-elles positives (every) ?
[ 'Amira : Clavier', 'Yasmine : Souris', 'Karim : Casque' ]
Chiffre d'affaires encaissé : 235.000 DT
[ 'Sami doit 420.000 DT', 'Amira doit 50.000 DT' ]
[ 'Écran', 'Clavier', 'Casque' ]
true true
-
Activité 4 : un minuteur de séance
- Dans
17-minuteur.js, écrire une classeMinuteuravec :- une propriété
restant(en secondes) initialisée par le constructeur ; - une méthode
demarrer()qui, toutes les secondes, diminuerestantet l'affiche, puis affiche « Fin de la séance ! » et s'arrête quand il atteint 0 (setIntervaletclearIntervalavec une fonction fléchée).
- une propriété
- Tester avec
new Minuteur(3).demarrer();. Résultat attendu :
- Dans
Il reste 2 s
Il reste 1 s
Il reste 0 s
Fin de la séance !
- Remplacer ensuite la fonction fléchée par
function () { … }et relancer. Le programme afficheIl reste NaN ssans jamais s'arrêter : l'interrompre avec Ctrl + C. Expliquer en commentaire : que vautthisdans la fonction classique ? Pourquoithis.restantdevient-ilNaN? Pourquoi la condition d'arrêt n'est-elle jamais vraie ? Revenir ensuite à la fonction fléchée. - À noter : ce bug est plus sournois que celui de
forEach. Appelée parsetInterval, la fonction classique ne reçoit pasundefinedmais un autre objet (l'objetTimeoutdans Node.js,windowdans le navigateur) : il n'y a donc aucune erreur, seulement un résultat faux.
Activité 5 : fabriques de fonctions
- Dans
18-fabriques.js, écrire deux fonctions qui renvoient des fonctions :creerFormateurPrix(devise, decimales = 3)renvoie une fonction qui formate un montant ;auMoins(minimum)renvoie une fonction, utilisable dansfilter, qui teste si la moyenne d'un stagiaire atteint le minimum.
- Tester avec le code suivant :
const enDinars = creerFormateurPrix('DT');
const enEuros = creerFormateurPrix('€', 2);
console.log(enDinars(45), enEuros(13.5));
const stagiaires = [
{ nom: 'Amira', moyenne: 15.5 }, { nom: 'Sami', moyenne: 9.75 },
{ nom: 'Yasmine', moyenne: 12 }, { nom: 'Karim', moyenne: 17.25 },
];
console.log(stagiaires.filter(auMoins(10)).map((s) => s.nom));
console.log(stagiaires.filter(auMoins(16)).map((s) => s.nom));
// Résultat attendu :
// 45.000 DT 13.50 €
// [ 'Amira', 'Yasmine', 'Karim' ]
// [ 'Karim' ]
- Faire un commit après chaque activité, puis un push :
git commit -m "Fonctions fléchées : activité N".
Erreurs fréquentes
| Message ou symptôme | Cause | Solution |
|---|---|---|
La fonction renvoie undefined |
Corps en bloc { } sans return |
Ajouter return, ou supprimer les accolades |
SyntaxError: Unexpected token ':', ou undefined au lieu d'un objet |
Objet renvoyé sans parenthèses | Écrire () => ({ … }) |
TypeError: Cannot read properties of undefined (reading 'x') dans un callback |
Fonction classique passée en callback : this perdu |
Utiliser une fonction fléchée |
Une méthode d'objet affiche undefined pour this.x |
Méthode écrite avec une fonction fléchée | Utiliser la syntaxe de méthode nom() { … } |
TypeError: X is not a constructor |
new appliqué à une fonction fléchée |
Utiliser une classe |
ReferenceError: Cannot access 'f' before initialization |
Fonction fléchée appelée avant sa définition | Déplacer la définition avant l'appel |
-
À retenir
- Une fonction fléchée s'écrit
(paramètres) => corps; avec un corps concis, la valeur est renvoyée automatiquement. - Pour renvoyer un objet en corps concis, on l'entoure de parenthèses :
() => ({ … }). - Une fonction fléchée n'a ni
this, niarguments, et ne peut pas être appelée avecnew. - Son
thisest celui du code qui l'entoure : c'est le bon choix pour tous les callbacks écrits dans une méthode de classe. - Méthode d'objet ou de classe → syntaxe de méthode ; fonction passée en paramètre → fonction fléchée.
- Une fonction fléchée s'écrit
Dans un composant Angular, chaque fois que vous passez une fonction àfilter,map,setTimeoutousubscribe, écrivez une fonction fléchée :thisrestera votre composant.