Apprenez en lisant dans l'ordre

Fonctions fléchées — formes courtes et renvoi d'objets

Réécrire une fonction avec =>, savoir quand omettre parenthèses et accolades, renvoyer un objet et écrire un corps en bloc.

Même pour un traitement court, comme mettre en forme chaque élément d'un tableau, une expression de fonction t'oblige à écrire à chaque fois function, des accolades et return, et le vrai calcul se perd au milieu de la syntaxe.

Les fonctions fléchées, qui créent des fonctions avec =>, allègent cette écriture ; nous verrons aussi les formes courtes qui se passent des parenthèses et des accolades.

Écrire la même fonction en plus court — la forme de base des fonctions fléchées

Les fonctions qui reçoivent une valeur, font un seul calcul et renvoient le résultat sont courantes : calculer les points de fidélité à partir d'un montant d'achat, par exemple. Pourtant, chacune demande le mot-clé function, des accolades et return ; quand les expressions de fonction s'accumulent, la syntaxe se voit plus que les calculs.

Une fonction fléchée (une façon de créer une fonction avec =>) s'écrit const nom = (paramètres) => { corps };. Tu supprimes le mot-clé function et tu places => entre la liste des paramètres et le corps ; ensuite, tu l'affectes à une variable et tu l'appelles exactement comme une expression de fonction.

// Ce que tu connais déjà : une expression de fonction, qui affecte une fonction à une variable
const rewardPoints = function (price) {
  return price * 0.02;
};

// Fonction fléchée
const rewardPointsArrow = (price) => {
  return price * 0.02;
};

console.log(rewardPoints(3200));        // 64
console.log(rewardPointsArrow(3200));   // 64
console.log(typeof rewardPointsArrow);  // function
D'une expression de fonction à une fonction fléchée
Expressionde fonctionconst nom =function (price){ returnprice * 0.02 }Renvoie 64pour 3200Fonctionfléchéeconst nom =(price) =>{ returnprice * 0.02 }Renvoie 64pour 3200Seule différence
L'affectation et le corps ne changent pas ; seule la partie centrale change. Le mot-clé function disparaît, et => suit les paramètres.

Les deux fonctions portent des noms différents uniquement pour pouvoir les comparer. Dans les deux cas, typeof donne function, et elles reçoivent leurs paramètres et utilisent return exactement de la même façon. Quand certaines conditions sont réunies, tu peux raccourcir encore cette forme de base en supprimant les parenthèses ou return.

Tu vas réécrire en fonction fléchée yearlyFee, une expression de fonction qui calcule le prix annuel d'un abonnement. standardMonthly et premiumMonthly sont aussi déjà déclarées.

① Transforme yearlyFee en fonction fléchée sans changer son comportement.

② Affiche le prix annuel des formules Standard et Premium sous la forme « Standard : X yens » et « Premium : X yens ».

③ Affiche l'écart entre les deux prix de ② sous la forme « Différence : X yens ».

(Si le code s'exécute correctement, une explication s'affiche.)

Éditeur JavaScript / TypeScript

Exécuter le code pour voir le résultat

Supprimer les parenthèses et return — un seul paramètre et return implicite

Certains calculs tiennent en une seule expression : ajouter les frais de port à un montant, vérifier si un total atteint 5000 yens. Avec la forme de base, même un calcul d'une ligne en prend trois une fois les accolades et return ajoutés, et quand ce genre de fonctions s'accumule, accolades et return occupent l'essentiel du code.

S'il y a exactement un paramètre, tu peux supprimer les parenthèses qui l'entourent. Et si le corps est une seule expression, tu peux aussi supprimer les accolades et return. C'est le return implicite (la règle selon laquelle la valeur de l'expression du corps devient directement la valeur de retour) qui rend cela possible.

// Forme de base : parenthèses du paramètre, accolades du corps et return, tout est écrit
const withFee = (price) => {
  return price + 500;
};

// Forme courte
const withFeeShort = price => price + 500;
const isFreeShipping = total => total >= 5000;

console.log(withFee(1200));          // 1700
console.log(withFeeShort(1200));     // 1700
console.log(isFreeShipping(4800));   // false
Raccourcir la même fonction, étape par étape
(price) => {return price + 500; }Rien d'omisprice => {return price + 500; }Un paramètre :sans ( )price =>price + 500Une expression :sans { } ni return
Les trois étapes ne diffèrent que par l'écriture ; elles font toutes le même calcul. Quelle que soit l'étape, si tu passes 1200, tu obtiens 1700.

Le corps de isFreeShipping est une seule comparaison : si tu passes 4800, tu récupères directement false, le résultat de 4800 >= 5000. Le return implicite renvoie la valeur de l'expression, quelle qu'elle soit ; un calcul et une comparaison s'écrivent donc exactement de la même façon.

Sans paramètre ou avec plusieurs, les parenthèses sont obligatoires

Si tu retires les parenthèses quand il n'y a aucun paramètre, comme dans () => expression, ou quand il y en a deux ou plus, comme dans (price, rate) => expression, tu obtiens une SyntaxError et le code ne démarre même pas. Si tu ajoutes un paramètre plus tard, pense à remettre les parenthèses. Avec un seul paramètre, tu peux aussi les garder : (price) => expression.

Tu vas créer des fonctions pour un devis de livraison, chacune avec un corps d'une seule expression. shippingFee et boxCount sont déjà déclarées.

① Écris discountFee en une ligne : elle reçoit des frais de port et renvoie le montant avec 10 % de remise (arrondi à l'entier inférieur).

② Écris totalFee en une ligne : elle reçoit des frais de port et un nombre de colis, et renvoie le total des frais de port.

③ Appelle ① et affiche « Après remise : X yens ».

④ Passe le résultat de ① à ② et affiche « Total après remise : X yens ».

Éditeur JavaScript / TypeScript

Exécuter le code pour voir le résultat

Renvoyer un objet — l'entourer de parenthèses

Quand tu mets en forme un enregistrement pour l'affichage, tu veux souvent renvoyer un objet avec plusieurs clés plutôt qu'un simple nombre. Mais si tu gardes la forme courte et que tu écris les accolades de l'objet juste après =>, tu obtiens undefined au lieu d'un objet.

Les accolades écrites après => sont lues comme un corps en bloc (une zone où tu peux écrire autant d'instructions que tu veux), et non comme un objet. Pour renvoyer un objet, entoure-le de parenthèses, comme dans (name) => ({ name: name }), afin que les accolades soient lues comme une expression.

// Des accolades seules sont lues comme un corps en bloc
const toBadge = (name) => { label: name };
console.log(toBadge("Souris sans fil"));   // undefined

// Entourées de parenthèses, les accolades sont lues comme un objet
const toCard = (name, stock) => ({ name: name, inStock: stock > 0 });
const card = toCard("Souris sans fil", 4);
console.log(JSON.stringify(card));         // {"name":"Souris sans fil","inStock":true}
console.log(card.inStock);                 // true
Corps en bloc ou objet ?
(name) =>{ label: name }Accolades luescomme un blocAucun returnécritRenvoie undefined(name) =>({ label: name })Le contenu des ( )est une expressionLes { } formentun objetRenvoieun objet
Les mêmes accolades sont lues différemment selon qu'elles sont entourées de parenthèses ou non. Sans parenthèses, les accolades forment un corps en bloc sans return.

Avec deux clés ou plus, comme dans { name: name, inStock: true }, le contenu ne peut pas être lu comme des instructions : une SyntaxError empêche le code de démarrer. Avec une seule clé, label: name se trouve être une instruction valide (une étiquette suivie d'une expression) ; il n'y a donc pas d'erreur et tu obtiens undefined sans t'en rendre compte tant que tu n'affiches pas le résultat.

Tu vas préparer des devis de livraison. orderTotals et freeLine sont déjà déclarées ; les frais de port sont de 500 yens en dessous de freeLine et gratuits sinon.

① Écris toQuote en une ligne : elle reçoit un montant et renvoie un objet avec les clés total et shippingFee, dans cet ordre.

② Affiche le premier devis avec JSON.stringify.

③ Pour le deuxième devis, affiche « Montant à payer : X yens » (montant + frais de port).

④ Affiche les frais de port des deux devis additionnés sous la forme « Total des frais de port : X yens ».

Éditeur JavaScript / TypeScript

Exécuter le code pour voir le résultat

Quand le corps tient sur plusieurs lignes — corps en bloc et return

Certaines fonctions doivent calculer une valeur intermédiaire ou choisir selon une condition avant de décider quoi renvoyer, comme le nombre de jours qui restent au client pour retourner un produit. La forme courte à une seule expression n'a aucun endroit où garder une valeur intermédiaire, ni aucun moyen de renvoyer une valeur différente selon la condition.

Un corps en bloc peut contenir des instructions comme const et if, mais le return implicite ne s'y applique pas : pour renvoyer une valeur, tu écris return. Une fonction peut contenir plusieurs return, et elle se termine sur celui qui s'exécute en premier.

// Corps d'une seule expression : la valeur de l'expression revient telle quelle
const shortMessage = (days) => `${days} jours depuis l'achat`;
console.log(shortMessage(12));           // 12 jours depuis l'achat

// Corps en bloc : calcule des valeurs intermédiaires et fait un return selon la condition
const returnMessage = (days, isOpened) => {
  const limit = isOpened ? 7 : 14;
  if (days > limit) {
    return "Délai de retour dépassé";     // La fonction se termine ici
  }
  return `Encore ${limit - days} jours`;
};
console.log(returnMessage(12, false));   // Encore 2 jours
console.log(returnMessage(12, true));    // Délai de retour dépassé

// Sans return, tu obtiens undefined
const brokenMessage = (days) => { `Encore ${days} jours`; };
console.log(brokenMessage(12));          // undefined
Produit ouvert ou non : le return atteint n'est pas le même
returnMessage(12, false)limit vaut 1412 > 14est fauxContinue jusqu'audernier returnreturnMessage(12, true)limit vaut 712 > 7est vraiS'arrête sur lereturn du if
Seul l'appel pour un produit déjà ouvert atteint le return situé dans le if. La fonction s'arrête là et n'atteint jamais le return qui suit.

Si tu écartes d'abord, avec un return, les cas qui ne remplissent pas la condition, les lignes suivantes n'ont plus qu'à traiter le cas normal. Le tableau ci-dessous montre ce que reçoit l'appelant selon la façon d'écrire le corps.

Écriture du corpsDans le corpsValeur reçue par l'appelant
days => expressionRenvoyée telle quelle12 jours depuis l'achat
(days, isOpened) => {… return}Valeur du returnEncore 2 jours / Délai de retour dépassé
days => { expression seule }Non renvoyéeundefined

this ne fonctionne pas comme dans les fonctions classiques

Dans la méthode d'un objet, tu peux utiliser this (un mot-clé qui désigne l'objet sur lequel la méthode a été appelée). Une fonction fléchée n'a pas son propre this : elle utilise celui du code qui l'entoure. L'article sur les classes, dans le chapitre sur la programmation orientée objet, revient sur cette différence.

Tu vas calculer combien d'unités commander pour réapprovisionner le stock, en lots complets. targetStock, currentStock et lotSize sont déjà déclarées.

① Écris planRestock, une fonction fléchée avec un corps en bloc qui reçoit le stock visé, le stock actuel et le nombre d'unités par lot.

② Dans le corps, calcule la quantité manquante et renvoie-la arrondie au lot supérieur (0 s'il ne manque rien).

③ Appelle-la avec le stock actuel et affiche « Unités à commander : X ».

④ Affiche le résultat de la même façon quand le stock actuel est égal au stock visé.

Éditeur JavaScript / TypeScript

Exécuter le code pour voir le résultat
QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Si tu déclares const twice = n => n * 2; puis que tu affiches twice(4), qu'est-ce qui s'affiche ?

Question 2Que renvoie un appel à const toItem = name => { label: name }; ?

Question 3Dans une fonction fléchée à deux paramètres, que se passe-t-il si tu supprimes les parenthèses qui les entourent ?