Les fonctions fléchées, introduites dans la spécification ECMAScript 6 (ES6), offrent une syntaxe plus concise pour la définition de fonctions en JavaScript, s'apparentant à des fontcions anonymes.
Syntaxe Complète
La forme complète est similaire aux fonctions anonymes traditionnleles, mais elle omet le mot-clé function.
const additionner = (a, b) => {
console.log(`Les valeurs sont : ${a}, ${b}`); // Les valeurs sont : 1, 2
return a + b;
};
console.log(additionner(1, 2)); // 3
// Équivalent à :
const additionnerNormal = function(a, b) {
console.log(`Les valeurs sont : ${a}, ${b}`); // Les valeurs sont : 1, 2
return a + b;
};
console.log(additionnerNormal(1, 2)); // 3
Paramètres Simplifiés
Si un seul paramètre est présent, les parenthèses peuvent être omises. Pour zéro ou plus de deux paramètres, les parenthèses sont obligatoires.
const doubler = nombre => {
console.log(`Le nombre est : ${nombre}`); // Le nombre est : 5
return nombre * 2;
};
console.log(doubler(5)); // 10
// Équivalent à :
const doublerNormal = function(nombre) {
console.log(`Le nombre est : ${nombre}`); // Le nombre est : 5
return nombre * 2;
};
console.log(doublerNormal(5)); // 10
Corps de Fonction Simplifié
Lorsque le corps de la fonction ne contient qu'une seule instruction, les accolades {} peuvent être omises. L'instruction sera alors implicitement retournée.
const comparer = (x, y) => x - y;
const nombres = [5, 1, 4, 2, 3];
const nombresTries = nombres.sort(comparer);
console.log(nombresTries); // [1, 2, 3, 4, 5]
// Équivalent à :
const comparerNormal = function(x, y) { return x - y; };
const nombres2 = [5, 1, 4, 2, 3];
const nombresTries2 = nombres2.sort(comparerNormal);
console.log(nombresTries2); // [1, 2, 3, 4, 5]
Syntaxe Complètement Simplifiée
Lorsque les deux conditions précédentes sont remplies (un seul paramètre et un corps de fonction d'une seule instruction), les parenthèses et les accolades peuvent être toutes deux omises.
const multiplierParDeux = val => val * 2;
console.log(multiplierParDeux(7)); // 14
// Équivalent à :
const multiplierParDeuxNormal = function(val) { return val * 2; };
console.log(multiplierParDeuxNormal(7)); // 14
Retour d'Objets Littéraux
Lorsqu'une fonction fléchée simplifiée doit retourner un objet littéral, celui-ci doit être enveloppé dans des parenthèses (). Sans cela, les accolades {} seraeint interprétées comme le début et la fin du corps de la fonction.
const creerObjet = id => ({ identifiant: id, valeur: id * 2 });
console.log(creerObjet(3)); // { identifiant: 3, valeur: 6 }
// Équivalent à :
const creerObjetNormal = function(id) { return { identifiant: id, valeur: id * 2 }; };
console.log(creerObjetNormal(3)); // { identifiant: 3, valeur: 6 }
Absence de Contexte this Propre
Les fonctions fléchées ne possèdent pas leur propre contexte this. Lors de l'utilisation de this à l'intérieur d'une fonction fléchée, il hérite de la valeur de this de son environnement englobant (lexical scope). Elles ne créent pas de nouveau this et ne peuvent pas modifier la valeur de this via apply, call ou bind.
const monObjet = {
nom: 'Objet Global',
methodeFlechee: () => {
console.log(`this dans la méthode fléchée : ${this.nom}`); // undefined ou contexte global
},
methodeNormale: function() {
console.log(`this dans la méthode normale : ${this.nom}`); // Objet Global
const methodeFlecheeInterne = () => {
console.log(`this dans la méthode fléchée interne : ${this.nom}`); // Objet Global
};
methodeFlecheeInterne();
}
};
monObjet.methodeFlechee();
monObjet.methodeNormale();
Cette caractéristique est particulièrement utile pour résoudre les problèmes courants de contexte this dans les fonctions de rappel.
Problème Classique de Contexte
const objContexte = {
valeur: 10,
demarrer: function() {
console.log(`Valeur initiale dans run: ${this.valeur}`); // 10
setTimeout(function() {
// Le contexte 'this' ici est celui de setTimeout (souvent l'objet window ou undefined en mode strict)
console.log(`Valeur dans setTimeout (normal): ${this.valeur}`); // undefined
}, 1000);
}
};
objContexte.demarrer();
Solution avec une Variable Intermédiaire
const objContexteVar = {
valeur: 10,
demarrer: function() {
const that = this; // Capture du contexte 'this'
setTimeout(function() {
console.log(`Valeur dans setTimeout (avec 'that'): ${that.valeur}`); // 10
}, 1000);
}
};
objContexteVar.demarrer();
Solution avec bind
const objContexteBind = {
valeur: 10,
demarrer: function() {
const callback = function() {
console.log(`Valeur dans setTimeout (avec bind): ${this.valeur}`); // 10
};
setTimeout(callback.bind(this), 1000); // Lier explicitement 'this'
}
};
objContexteBind.demarrer();
Solution avec Fonction Fléchée
Les fonctions fléchées simplifient grandement ce scénario, car elles héritent le this de leur portée englobante.
const objContexteFleche = {
valeur: 10,
demarrer: function() {
// La fonction fléchée hérite le 'this' de la méthode demarrer
setTimeout(() => {
console.log(`Valeur dans setTimeout (fléchée): ${this.valeur}`); // 10
}, 1000);
}
};
objContexteFleche.demarrer();
Absence d'Objet arguments Propre
Les fonctions fléchées ne disposent pas de leur propre objet arguments. Si vous y accédez, il s'agira d'une référence à l'objet arguments de la portée englobante.
function fonctionPrincipale(a, b) {
console.log(`Arguments de fonctionPrincipale: ${arguments.length}`); // 2
const fonctionFlecheeInterne = (...args) => {
// Utilise les arguments de fonctionPrincipale s'ils sont disponibles dans la portée, sinon ses propres arguments s'ils sont passés.
// Dans ce cas, si on appelle ss1(3), 'arguments' fait référence à ceux de fonctionPrincipale.
console.log(`Arguments de fonctionFlecheeInterne (simulés): ${args}`); // 1, 2
};
const fonctionNormaleInterne = function(...args) {
// 'arguments' fait référence aux arguments de cette fonction interne.
console.log(`Arguments de fonctionNormaleInterne: ${args}`); // 3
};
fonctionFlecheeInterne(a, b); // Passe les arguments originaux
fonctionNormaleInterne(3); // Passe de nouveaux arguments
}
fonctionPrincipale(1, 2);
Non utilisables comme Constructeurs
Les fonctions fléchées ne peuvent pas être utilisées comme constructeurs avec l'opérateur new. Une tentative entraînera une erreur.
const MaFonctionFlechee = () => {};
try {
new MaFonctionFlechee();
} catch (e) {
console.error(e.message); // MaFonctionFlechee is not a constructor
}
Absence de Propriété prototype
Étant donné qu'elles ne peuvent pas être utilisées comme constructeurs, les fonctions fléchées n'ont pas de propriété prototype.
const fonctionSimple = () => {};
console.log(fonctionSimple.prototype); // undefined
Non utilisables comme Générateurs
Les fonctions fléchées ne peuvent pas être utilisées comme fonctions génératrices. Le mot-clé yield n'est généralement pas applicable à l'intérieur d'une fonction fléchée, sauf si elle est imbriquée dans une fonction qui autorise yield.