Fonctions JavaScript, portée et fermetures

Apprends à organiser le code JavaScript en fonctions réutilisables. Écris des déclarations de fonction, des expressions de fonction et des fonctions fléchées ; transmets-leur des valeurs à l’aide de paramètres, de valeurs par défaut et de paramètres du reste ; et renvoie des résultats avec return. Détermine où une variable peut être utilisée grâce à la portée de bloc, de fonction et globale, utilise des fermetures pour donner aux fonctions leur propre mémoire et passe des fonctions à d’autres fonctions comme fonctions de rappel pour écrire du code d’ordre supérieur flexible.

DébutantUnité 3 sur 9 de la formation Formation : JavaScript : DOM, événements et code asynchrone

Ce que tu vas apprendre

  1. Organise un morceau de code réutilisable sous forme de fonction, appelle-le avec des arguments et choisis entre une déclaration de fonction, une expression de fonction et une fonction fléchée.
    • Déclare une fonction et appelle-la
      Définis une fonction nommée avec le mot-clé function, appelle-la et explique pourquoi les fonctions rendent le code plus court, plus clair et plus facile à modifier.
    • Stocke une fonction dans une variable avec une expression de fonction
      Traite les fonctions comme des valeurs : crée une expression de fonction, affecte-la à une variable et explique en quoi elle diffère d’une déclaration pour la remontée et le nommage.
    • Écris des fonctions fléchées
      Utilise la syntaxe courte des fonctions fléchées, sache quand elles renvoient automatiquement une valeur et explique en quoi elles diffèrent des fonctions écrites avec function.
  2. Conçois les entrées et les sorties d’une fonction : fais correspondre les arguments aux paramètres, définis des valeurs par défaut, accepte un nombre quelconque d’arguments, renvoie des résultats et suis l’exécution des appels imbriqués.
    • Fais correspondre les arguments aux paramètres
      Explique comment les valeurs d’un appel sont transmises aux paramètres de la fonction, ce qui se passe lorsqu’il y a trop peu ou trop d’arguments et quelles données du code appelant une fonction peut modifier.
    • Définis des valeurs par défaut et accepte un nombre quelconque d’arguments
      Donne des valeurs par défaut aux paramètres, regroupe un nombre quelconque d’arguments avec un paramètre du reste et décompose un tableau en arguments distincts.
    • Renvoie des résultats depuis une fonction
      Renvoie une valeur avec return, utilise le résultat dans la suite du code et distingue le renvoi d’une valeur de son affichage ou de la modification d’un élément extérieur à la fonction.
    • Suis les appels de fonctions dans la pile d’appels
      Suis l’ordre dans lequel les appels imbriqués s’exécutent et renvoient leurs résultats, puis écris une fonction récursive simple avec un cas de base.
  3. Détermine où une variable est visible en appliquant les règles de portée de bloc, de fonction et globale, ainsi que celles des fonctions écrites dans d’autres fonctions.
    • Distingue la portée de bloc, la portée de fonction et la portée globale
      Explique la portée d’une variable déclarée avec let, const ou var, et utilise des variables locales pour que les fonctions restent indépendantes les unes des autres.
    • Détermine à quelle variable un nom fait référence
      Suis la chaîne de portées pour trouver la variable associée à un nom, reconnais le masquage et explique la remontée des déclarations et la zone morte temporaire.
  4. Explique comment une fonction conserve l’accès aux variables qui l’entourent après la fin de la fonction extérieure, et utilise ce mécanisme pour construire des fabriques de fonctions et conserver un état privé.
    • Explique ce qu’une fermeture conserve en mémoire
      Décris comment une fonction conserve l’accès aux variables de la portée dans laquelle elle a été créée, même après le retour de la fonction extérieure.
    • Utilise des fermetures pour créer des fabriques de fonctions et conserver un état privé
      Construis des fabriques de fonctions, garde des données privées derrière des fonctions et évite l’erreur classique liée aux fermetures dans une boucle.
  5. Utilise les fonctions comme des valeurs : transmets-les à d’autres fonctions comme fonctions de rappel, utilise et écris des fonctions d’ordre supérieur, et construis de nouvelles fonctions à partir de fonctions existantes.
    • Passe une fonction de rappel à une fonction
      Transmets une fonction à une autre comme argument, écris des fonctions qui appellent une fonction de rappel et transmets la fonction elle-même plutôt que son résultat.
    • Utilise et écris des fonctions d’ordre supérieur
      Reconnais les fonctions d’ordre supérieur, utilise les méthodes de tableau qui acceptent des fonctions de rappel et écris ta propre fonction qui reçoit une fonction en entrée.
    • Construis de nouvelles fonctions à partir de fonctions existantes
      Écris des fonctions d’ordre supérieur qui enveloppent, combinent ou renseignent à l’avance d’autres fonctions, en utilisant des fermetures pour conserver en mémoire la fonction reçue.

Fonctions JavaScript : cours

5 chapitres

1

Définis et appelle des fonctions sous trois formes

Les fonctions transforment des instructions répétées en tâches nommées. Tu vas lire et écrire trois formes courantes, puis déterminer si une ligne crée une fonction, en stocke une ou en appelle une. De petites différences de syntaxe comptent : une déclaration est disponible dès le début, tandis qu’une expression stockée doit d’abord être initialisée, et le corps d’une fonction fléchée peut déterminer si un résultat est renvoyé. Ces distinctions te préparent à transmettre les fonctions comme des valeurs ordinaires.

1.1 Déclare une fonction et appelle-la

Une fonction donne un nom à une tâche et enregistre les instructions nécessaires pour l’accomplir. La définir n’exécute pas ces instructions. Un appel les exécute, et un autre appel les exécute à nouveau avec de nouvelles entrées.

Écris la définition

Une déclaration comporte le mot-clé function, un nom, des parenthèses pour les paramètres et des accolades pour le corps :

function greet(name) {
  console.log("Hello, " + name + "!");
}

Ici, name est un paramètre : un nom local pour l’entrée fournie par chaque appel. Le corps joint cette entrée au texte qui l’entoure et affiche le résultat. L’accolade fermante marque la fin de la définition ; l’exécution se poursuit avec l’instruction suivante à l’extérieur de celle-ci.

Une fonction sans entrée a tout de même besoin de parenthèses. Par exemple, function sayHi() { console.log("Hi"); } définit une tâche avec une liste de paramètres vide. Les accolades appartiennent à la définition ; les parenthèses après un nom figurent à la fois dans les définitions et dans les appels, avec des rôles différents.

Exécute la tâche
greet("Amira");
greet("Li");

Le premier appel donne à name la valeur "Amira" et affiche « Hello, Amira! ». Le second lance un nouvel appel avec name égal à "Li" et affiche « Hello, Li! ». La définition est partagée ; l’entrée appartient à chaque appel.

greet seul fait référence à la valeur de la fonction. Il n’exécute pas le corps. Cette distinction compte lorsqu’une ligne semble ne rien faire : sayHi; lit une valeur de fonction et l’ignore, tandis que sayHi(); affiche « Hi ».

Remplace les instructions copiées

Supposons que plusieurs rapports aient besoin d’un titre entouré de lignes :

function printHeading(title) {
  console.log("-----");
  console.log(title);
  console.log("-----");
}

printHeading("Report");
printHeading("Totals");

Le premier appel affiche une ligne, « Report », puis une autre ligne. Le second affiche le même encadrement autour de « Totals ». Pour changer le style des lignes, modifie les deux instructions qui les affichent dans cette seule définition. Sans la fonction, chaque titre copié devrait être corrigé séparément.

Choisis un nom qui indique ce que fait un appel. printHeading décrit une action ; isValidEmail nomme une vérification dont la réponse est oui ou non. Utilise camelCase, avec un premier mot en minuscules et une majuscule au début des mots suivants. Si un nom proposé relie deux tâches distinctes par « et », envisage de donner à chaque tâche sa propre fonction.

Lis du code qui appelle une déclaration avant son emplacement

Les déclarations sont mises en place avant l’exécution du code qui les entoure. Ce comportement s’appelle la remontée des déclarations :

sayHi();
function sayHi() {
  console.log("Hi");
}

L’appel fonctionne dans la portée de la déclaration, même si la définition est écrite plus loin. La remontée des déclarations n’exécute pas le corps plus tôt ; elle rend la fonction disponible pour un appel.

Vérifie l’orthographe et les majuscules lorsqu’un appel échoue. Greet() et greet() sont des noms différents. Appeler un greeet() non déclaré provoque une ReferenceError ; oublier les parenthèses d’appel peut échouer silencieusement, car lire une fonction existante est un code valide.

Points clés

  • Définir une fonction enregistre des instructions ; l’appeler les exécute.
  • Appelle une fonction avec des parenthèses, même sans argument.
  • Une déclaration est disponible avant l’endroit où elle est écrite, dans la même portée.
  • Nomme une tâche claire pour n’avoir qu’un seul endroit où modifier le code répété.

1.2 Stocke une fonction dans une variable avec une expression de fonction

Les fonctions sont des valeurs. Tu peux en conserver une dans une variable, copier sa référence, la passer à une autre fonction ou la renvoyer. Une expression de fonction crée cette valeur là où une expression est attendue.

Stocke une fonction
const square = function (n) {
  return n * n;
};

const answer = square(4);

L’expression après = crée une fonction. L’affectation la stocke dans square ; l’appel qui suit renvoie 16. Cette instruction se termine par un point-virgule, conformément à la convention de mise en forme utilisée ici.

La position de function distingue les formes. Une définition écrite seule sous la forme function square(n) { ... } est une déclaration. Une fonction écrite après = ou directement comme argument d’un appel est une expression. Les deux formes de fonction ordinaire peuvent accepter des paramètres et renvoyer des valeurs.

Utilise const pour une variable contenant une fonction lorsque sa valeur doit rester la même. Appeler square(5) est autorisé ; l’affectation square = 5; provoque une TypeError. La constante protège la variable contre son remplacement. Elle n’empêche pas les appels répétés.

Conserve une fonction ou son résultat
const sq = square;
const result = square(3);

sq fait référence à la même fonction que square. Appeler sq(3) renvoie 9. result contient le nombre 9 renvoyé par un appel. Il ne peut pas être appelé comme une fonction. typeof square et typeof sq valent "function" ; typeof result vaut "number".

Lire une affectation de droite à gauche aide à la comprendre : détermine d’abord si son membre de droite crée une fonction, fait référence à une fonction existante ou en appelle une. La variable de gauche reçoit cette valeur. Copier la référence ne crée pas une deuxième implémentation indépendante.

Attends l’exécution de l’affectation

Une déclaration et une expression stockée ne deviennent pas appelables au même moment :

FormeAvant la définition ou l’affectation écrite
function square(n) { return n * n; }Appelable dans sa portée
const square = function (n) { return n * n; };Lire square provoque une ReferenceError
var square = function (n) { return n * n; };square vaut undefined ; l’appeler provoque une TypeError

Avec const ou let, le nom ne peut pas être utilisé avant l’initialisation. Avec var, le nom existe dès le début, mais la valeur de fonction n’est affectée que lorsque l’exécution atteint l’expression. La remontée de la variable ne fait pas remonter l’affectation.

Donne un nom interne à une expression
const factorial = function fact(n) {
  return n <= 1 ? 1 : n * fact(n - 1);
};

Le nom extérieur est factorial. Le nom fact appartient à la fonction et lui permet de s’appeler elle-même ; le code extérieur ne peut pas utiliser directement ce nom interne. Le nom de l’expression peut aussi faciliter la lecture des traces de pile. Par exemple, factorial(3) calcule 3 fois 2 fois 1 et renvoie 6.

Les déclarations conviennent bien aux principales tâches nommées d’un script. Les expressions conviennent aux endroits où le code a besoin d’une valeur de fonction, comme une affectation à une variable ou un argument. Choisir une expression change la manière dont la valeur est créée et stockée, mais pas la manière dont les parenthèses l’appellent.

Points clés

  • Une expression de fonction crée une valeur de fonction à l’intérieur d’une autre expression.
  • Affecter square copie une référence de fonction ; affecter square(3) stocke son résultat.
  • Une expression de fonction stockée dans const ne peut être appelée qu’après son initialisation.
  • Une variable de fonction déclarée avec var contient undefined avant l’exécution de son affectation.
  • Une expression nommée peut utiliser son nom interne pour s’appeler elle-même.

1.3 Écris des fonctions fléchées

Les fonctions fléchées sont des expressions de fonction dont l’écriture est plus courte. Ce qu’elles renvoient dépend de ce qui suit la flèche : examine donc le corps avant de déterminer ce que produit un appel.

Choisis la forme des paramètres
const sayHi = () => "hi";
const double = n => n * 2;
const add = (a, b) => a + b;

Sans paramètre, des parenthèses vides sont nécessaires. Avec un seul paramètre simple, les parenthèses peuvent être omises. À partir de deux paramètres, elles sont obligatoires. Un paramètre par défaut ou du reste exige aussi des parenthèses : (n = 1) => n * 2 et (...nums) => nums.length sont valides.

La flèche sépare les entrées du corps. const double = n => n * 2; crée la fonction et la stocke ; double(6) l’appelle ensuite et renvoie 12. Comme toute variable const contenant une expression de fonction, double ne peut pas être lue avant l’exécution de sa ligne d’initialisation.

Renvoie une expression ou écris un bloc
CorpsExempleRésultat de l’appel avec 2 et 3
Expression concise(a, b) => a + b5
Bloc avec return(a, b) => { return a + b; }5
Bloc sans return(a, b) => { a + b; }undefined

Un corps concis renvoie automatiquement son expression. Des accolades ouvrent un bloc d’instructions. Dans un bloc, évaluer une expression ne la renvoie pas au code appelant ; écris return explicitement.

Utilise un bloc lorsque la tâche nécessite des étapes intermédiaires :

const describe = (n) => {
  const kind = n % 2 === 0 ? "even" : "odd";
  return n + " is " + kind;
};

Pour describe(7), la condition est fausse, donc kind prend la valeur "odd". L’instruction de retour réunit ensuite le nombre et les mots pour former « 7 is odd ». Supprimer ce retour conserverait le calcul local, mais fournirait undefined au code appelant.

Renvoie un littéral d’objet

Un littéral d’objet utilise lui aussi des accolades. Entoure-le de parenthèses pour que l’analyseur syntaxique le traite comme une expression :

const makePoint = (x, y) => ({ x: x, y: y });

makePoint(2, 5) renvoie un objet dont x vaut 2 et y vaut 5. Sans les parenthèses, la première accolade ouvre un bloc. La forme à une propriété () => { value: 1 } renvoie undefined ; la forme similaire à deux propriétés séparées par une virgule produit une erreur de syntaxe. Les parenthèses changent la manière dont le corps est interprété.

Connais les limites de la forme courte

Les fonctions fléchées n’ont pas leur propre this ni leur propre arguments, et elles ne peuvent pas être appelées avec new pour construire des objets. Pour un calcul simple qui n’utilise ni this ni arguments, une fonction fléchée et une expression de fonction ordinaire se comportent de la même manière. Remplacer toutes les fonctions ordinaires par des fonctions fléchées peut modifier le comportement du code qui dépend de ces caractéristiques.

Les fonctions fléchées courtes sont particulièrement lisibles comme fonctions de rappel. [1, 2, 3].map(n => n * 10) transmet une fonction qui renvoie un élément transformé, ce qui produit [10, 20, 30]. La remplacer par n => { n * 10; } fait perdre silencieusement chaque valeur de retour.

Points clés

  • Un corps concis de fonction fléchée renvoie automatiquement son expression.
  • Un corps de bloc de fonction fléchée a besoin d’un return explicite pour renvoyer une valeur calculée.
  • Entoure de parenthèses un littéral d’objet renvoyé par une fonction fléchée à corps concis.
  • Les listes de paramètres vides ou multiples et les paramètres par défaut ou du reste nécessitent des parenthèses.
  • Les fonctions fléchées n’ont pas leur propre this ni leur propre arguments et ne peuvent pas servir de constructeurs.
2

Passe des valeurs aux fonctions et récupère leurs résultats

Un appel de fonction comporte des entrées et une sortie. Fais correspondre les arguments aux paramètres, gère les entrées facultatives ou en nombre variable et suis la valeur renvoyée au code appelant. Tu vas aussi distinguer les modifications locales de celles apportées à un tableau partagé, et suivre les appels imbriqués lorsque leur exécution se suspend puis reprend. Le même modèle d’appel et de retour explique la récursivité simple, dans laquelle plusieurs appels d’une fonction attendent la fin d’appels portant sur des problèmes plus petits.

2.1 Fais correspondre les arguments aux paramètres

Les paramètres d’une fonction donnent des noms aux valeurs fournies par un appel. Pour suivre un appel, fais d’abord correspondre les entrées selon leur position, puis suis les opérations dans le corps.

Fais correspondre les positions et les types
function area(width, height) {
  return width * height;
}

area(4, 2.5);

width et height sont des paramètres ; 4 et 2,5 sont des arguments. Pendant cet appel, width contient 4 et height contient 2,5 : le résultat est donc 10. Les noms des paramètres ne correspondent pas à ceux des variables du code appelant. Avec divide(a, b), remplacer divide(10, 2) par divide(2, 10) fait passer le résultat de 5 à 0,2.

JavaScript n’impose pas de nombre d’arguments. area(4) laisse height à undefined ; multiplier par cette valeur produit NaN. area(4, 2, 99) renvoie 8 parce que ce corps n’utilise pas le troisième argument. Une fonction peut choisir de regrouper les arguments supplémentaires, mais ceux qui ne sont pas utilisés ne provoquent pas automatiquement d’erreur.

Les types comptent aussi, même lorsque l’appel est accepté. area("4", 2) renvoie 8 parce que la multiplication convertit le texte. Une fonction d’addition se comporte différemment : add("4", 2) renvoie « 42 » lorsque son corps est return a + b;. Si le texte représente un nombre, add(Number("4"), 2) renvoie 6.

Réaffecte un paramètre local

Chaque paramètre est local à son appel. Lui affecter un nouveau nombre ne réaffecte pas la variable du code appelant :

let score = 5;
function reset(s) {
  s = 0;
}
reset(score);

L’appel copie la valeur 5 dans s. L’affectation donne à s la valeur 0, et score reste égal à 5. Les nombres, les chaînes de caractères et les booléens suivent cette règle de copie de valeur. Le code extérieur ne peut pas lire s directement ; une fonction imbriquée peut en conserver l’accès grâce à une fermeture.

Modifie un tableau à travers une référence copiée

Une valeur de tableau est une référence à un tableau. Transmettre cette valeur copie la référence, de sorte que le code appelant et le paramètre peuvent accéder au même tableau :

const list = [1, 2];
function addItem(arr) {
  arr.push(3);
}
addItem(list);

list vaut maintenant [1, 2, 3]. La fonction n’a pas réaffecté list ; elle a modifié le tableau auquel les deux noms donnent accès. Une déclaration const empêche de remplacer la référence stockée, mais pas de modifier le contenu du tableau.

Compare avec une réaffectation locale :

function clearLocal(arr) {
  arr = [];
}
clearLocal(list);

Cela fait pointer uniquement arr vers un nouveau tableau vide. list donne toujours accès à [1, 2, 3]. Demande-toi si une opération modifie un tableau existant, comme le fait push, ou donne une autre valeur à un nom, comme le fait =.

Renvoie un nouveau tableau lorsque l’entrée doit rester intacte
function withItem(arr, item) {
  return arr.concat(item);
}

withItem([1, 2], 3) produit un nouveau tableau, [1, 2, 3]. Le tableau d’entrée reste [1, 2]. Cela rend la fonction utile lorsque le code appelant a besoin à la fois de l’ancienne liste et de la liste complétée. Indique par le nom et le comportement d’une fonction les modifications qu’elle est censée apporter à ses entrées, afin que le code appelant puisse l’utiliser de manière prévisible.

Points clés

  • Les arguments correspondent aux paramètres selon leur position.
  • Un argument manquant fournit undefined ; les arguments supplémentaires inutilisés sont autorisés.
  • Réaffecter un paramètre ne réaffecte pas la variable du code appelant.
  • Modifier un tableau par l’intermédiaire d’un paramètre modifie le tableau partagé.
  • Renvoyer un nouveau tableau permet de préserver l’entrée.

2.2 Définis des valeurs par défaut et accepte un nombre quelconque d’arguments

Les valeurs par défaut rendent une entrée facultative ; les paramètres du reste permettent à un appel de fournir de nombreuses entrées. La syntaxe de décomposition relie un tableau existant à une fonction qui attend des arguments distincts.

Applique une valeur par défaut uniquement pour undefined
function greet(name = "friend") {
  return "Hello, " + name;
}

greet() et greet(undefined) renvoient tous deux « Hello, friend ». greet(null) renvoie « Hello, null » et greet("") renvoie « Hello, ». Une valeur par défaut est utilisée pour undefined, mais pas pour toute valeur qui semble vide.

Les valeurs par défaut sont évaluées lorsqu’un appel en a besoin. Elles peuvent utiliser les paramètres précédents : function makeBox(width, height = width) { return width * height; } renvoie 9 pour makeBox(3) et 12 pour makeBox(3, 4). Le deuxième argument explicite remplace la valeur par défaut pour cet appel.

Place d’abord les entrées obligatoires. Avec function total(amount, rate = 0.25) { return amount + amount * rate; }, total(80) renvoie 100 et total(80, 0.5) renvoie 120. Inverser les paramètres obligerait à écrire total(undefined, 80) pour effectuer l’appel courant qui utilise le taux par défaut.

Le code ancien peut utiliser level = level || 50;. Cela remplace aussi 0, false et une chaîne vide, car ce sont des valeurs fausses. Un paramètre par défaut conserve ces valeurs : function setVolume(level = 50) { return level; } renvoie 0 pour setVolume(0) et 50 pour setVolume(undefined).

Regroupe les arguments avec le reste
function sum(...numbers) {
  let total = 0;
  for (const n of numbers) {
    total += n;
  }
  return total;
}

sum(1, 2, 3) place [1, 2, 3] dans numbers et renvoie 6. sum() lui fournit un tableau vide : la boucle n’ajoute donc rien et la fonction renvoie 0. Un paramètre du reste est un véritable tableau, prêt à être parcouru ou utilisé avec les méthodes de tableau.

Une entrée fixe peut précéder le reste : dans function log(label, ...values) { console.log(label, values); }, log("scores", 7, 9) donne à label la chaîne « scores » et à values le tableau [7, 9]. Un seul paramètre du reste est autorisé et il doit être placé en dernier ; sinon, JavaScript ne peut pas affecter les arguments restants sans ambiguïté avec cette syntaxe.

Décompose les arguments
Emplacement de ...RôleExemple
Liste de paramètres de la définitionRegrouper les arguments restantsfunction sum(...numbers) { ... }
Liste d’arguments de l’appelDécomposer les éléments du tableausum(...values)

Math.max(...[3, 7, 2]) reçoit trois nombres et renvoie 7. Math.max([3, 7, 2]) reçoit un tableau et renvoie NaN. Les trois points sont identiques à l’écrit, mais la syntaxe qui les entoure indique leur rôle.

Les fonctions ordinaires possèdent aussi un objet arguments contenant les arguments qui leur sont transmis. Il ressemble à un tableau, avec des entrées indicées et une longueur, mais ce n’est pas un véritable tableau et il ne possède pas ses propres méthodes map ou filter. Les fonctions fléchées n’ont pas leur propre arguments. Pour un nouveau code qui a besoin d’une liste d’entrées de longueur variable, privilégie un paramètre du reste.

Points clés

  • Les valeurs par défaut s’appliquent aux arguments manquants et à undefined explicite, tout en préservant 0 et null.
  • Une expression par défaut est évaluée pour chaque appel qui en a besoin.
  • Un seul paramètre du reste regroupe les arguments restants dans un tableau et vient en dernier.
  • La décomposition sépare un tableau en arguments d’appel distincts.
  • L’ancien objet arguments ressemble à un tableau ; le reste produit un véritable tableau.

2.3 Renvoie des résultats depuis une fonction

Une valeur de retour est la sortie que le code reçoit d’un appel. L’affichage peut montrer la même valeur à l’écran, mais il donne au code appelant un résultat différent, sauf si la fonction renvoie aussi cette valeur.

Utilise l’appel comme une valeur
function double(n) {
  return n * 2;
}
const x = double(5) + 1;

double(5) renvoie 10 : l’affectation calcule donc 10 plus 1 et stocke 11. Un appel peut apparaître partout où une valeur appropriée est nécessaire. double(double(3)) obtient d’abord 6 de l’appel intérieur, puis renvoie 12 depuis l’appel extérieur. Math.round(double(2.3)) double la valeur pour obtenir 4,6 et l’arrondit à 5.

return termine aussi immédiatement l’appel en cours. Une clause de garde traite un cas particulier avant le traitement principal :

function safeDivide(a, b) {
  if (b === 0) {
    return null;
  }
  return a / b;
}

safeDivide(6, 0) renvoie null et n’atteint jamais la division. safeDivide(6, 2) passe la clause de garde et renvoie 3. Place la condition avant l’opération qu’elle protège.

Distingue le résultat de l’affichage
function addLog(a, b) {
  console.log(a + b);
}

addLog(2, 3) affiche 5, mais sa valeur de retour est undefined. Par conséquent, addLog(2, 3) * 2 affiche 5 et vaut NaN. Une fonction qui atteint sa fin sans retour ou exécute un simple return; renvoie undefined. L’affichage dans la console est un effet de bord, et non le résultat numérique exploitable de l’appel.

Si le code appelant a besoin d’une somme, écris return a + b;. Il peut alors choisir de l’afficher, de la stocker ou de l’utiliser dans un autre calcul. Les décisions d’affichage restent ainsi séparées d’un calcul réutilisable.

Garde l’expression renvoyée sur la même ligne
function brokenAdd(a, b) {
  return
  a + b;
}

JavaScript termine l’instruction return au passage à la ligne. La fonction renvoie undefined ; l’expression suivante n’est jamais atteinte. Pour une longue expression, commence-la ou ouvre une parenthèse sur la ligne de return, puis poursuis en dessous.

Regroupe plusieurs résultats dans une valeur

Un appel renvoie une valeur, mais cette valeur peut être un tableau :

function minMax(nums) {
  return [Math.min(...nums), Math.max(...nums)];
}
const [low, high] = minMax([4, 9, 1]);

Le tableau renvoyé est [1, 9]. La déstructuration affecte son premier élément à low et son second à high. Il y a toujours une seule valeur renvoyée, qui contient deux résultats utiles.

Une fonction pure calcule sa sortie à partir de ses arguments et ne modifie rien à l’extérieur d’elle-même. double est pure. Afficher une valeur, mettre à jour une variable extérieure et modifier un tableau d’entrée sont des effets de bord. Les calculs purs sont faciles à vérifier avec des exemples d’entrées et de sorties ; place les effets de bord dans des fonctions clairement nommées là où le programme a besoin de changements visibles.

Points clés

  • return fournit la valeur de l’appel et termine l’appel en cours.
  • Un simple affichage laisse la valeur de retour de la fonction à undefined.
  • Commence l’expression renvoyée sur la ligne de return.
  • Un tableau renvoyé peut contenir plusieurs résultats.
  • Les fonctions pures dépendent de leurs arguments et ne modifient rien à l’extérieur.

2.4 Suis les appels de fonctions dans la pile d’appels

Lorsqu’une fonction en appelle une autre, la fonction appelante se met en pause jusqu’au retour de cet appel. La pile d’appels conserve la trace du travail inachevé pour que l’exécution puisse reprendre au bon endroit.

Ajoute et retire des cadres de pile

Chaque appel actif possède un cadre de pile qui contient ses paramètres, ses variables locales et l’endroit où reprendre après son retour. Un nouvel appel est placé au sommet de la pile ; un retour retire ce cadre supérieur.

function square(n) {
  return n * n;
}
function sumOfSquares(a, b) {
  return square(a) + square(b);
}
sumOfSquares(3, 4);

D’abord, sumOfSquares commence avec a égal à 3 et b égal à 4. Elle appelle square(3), qui renvoie 9 et se termine. Puis square(4) s’exécute et renvoie 16. L’addition en pause peut alors se terminer : 9 plus 16, et sumOfSquares renvoie 25. Les deux appels de square ne se chevauchent pas dans ce suivi.

Chaque appel reçoit des paramètres et des variables locales créés pour lui. Appeler deux fois la même fonction ne réutilise pas l’état numérique local d’un appel précédent. Même lorsqu’une fonction s’appelle elle-même, le nouvel appel possède son propre cadre.

Réduis un problème par récursivité

Une fonction récursive s’appelle elle-même. Un cas de base se termine sans nouvel appel à elle-même ; un cas récursif se rapproche de ce cas de base.

function factorial(n) {
  if (n <= 1) {
    return 1;
  }
  return n * factorial(n - 1);
}

Pour des entrées entières positives ou nulles, cette fonction multiplie les entiers jusqu’à 1. Suis factorial(4) dans les deux sens :

  1. factorial(4) attend factorial(3).
  2. Cet appel attend factorial(2).
  3. Cet appel attend factorial(1).
  4. Le cas de base renvoie 1.
  5. Les appels en attente renvoient 2, puis 6, puis 24.

La multiplication dans l’appel où n vaut 4 a lieu après le retour de l’appel portant sur le problème plus petit. Son propre n est resté égal à 4 pendant l’attente.

Un cas de base doit pouvoir être atteint. Utiliser seulement n === 1 échoue pour une entrée initiale de 0 si chaque appel récursif soustrait 1 : les valeurs deviennent négatives et n’atteignent jamais 1. n <= 1 prend en compte à la fois 0 et 1. Sans chemin permettant l’arrêt, les appels répétés épuisent la pile. Chrome et Node.js indiquent « RangeError: Maximum call stack size exceeded » ; Firefox utilise « InternalError: too much recursion ».

Reconnais une version plus petite de la même tâche
function countItems(list) {
  let count = 0;
  for (const item of list) {
    if (Array.isArray(item)) {
      count += countItems(item);
    } else {
      count += 1;
    }
  }
  return count;
}

countItems([1, [2, 3], [4, [5]]]) renvoie 5. Pour chaque tableau imbriqué, la même question de comptage se pose sur une liste plus petite. Une boucle convient aussi pour une factorielle simple ; la récursivité est particulièrement utile lorsque les données elles-mêmes sont imbriquées.

Si un appel échoue, lis la trace de pile en commençant par l’appel le plus récent, en haut. Les entrées suivantes montrent quels appels encore inachevés y ont conduit. Des entrées répétées pour une fonction peuvent révéler une récursivité qui ne s’est pas arrêtée.

Points clés

  • La pile d’appels suit les appels inachevés ; les retours retirent le cadre le plus récent.
  • Chaque appel possède ses propres paramètres et variables locales.
  • La récursivité a besoin d’un cas d’arrêt et d’une progression vers celui-ci.
  • Les résultats récursifs sont renvoyés par les appels en attente dans l’ordre inverse.
  • Une trace de pile montre l’appel qui a échoué et les appels qui y ont conduit.
  • Des données imbriquées peuvent contenir des versions plus petites de la même tâche.
3

Explique où une variable peut être utilisée

Les noms de variables ont un sens à l’intérieur de portées. Les limites des blocs et des fonctions, ainsi que l’endroit où une fonction est définie, déterminent les déclarations auxquelles elle peut accéder. Tu vas suivre ces limites pour prévoir une valeur ou une erreur, puis distinguer le masquage de la mise à jour d’une variable extérieure. La remontée des déclarations et la zone morte temporaire expliquent pourquoi un nom peut être enregistré avant que l’exécution atteigne sa ligne tout en restant inutilisable.

3.1 Distingue la portée de bloc, la portée de fonction et la portée globale

La portée d’une variable est la partie du code où son nom peut être utilisé. La portée permet aux fonctions de garder leurs données de travail séparées tout en utilisant des entrées et des valeurs du code environnant.

Délimite les portées des déclarations

let et const ont une portée de bloc. Un bloc est une partie du code entre accolades, comme un corps if, un corps de boucle ou un corps de fonction :

if (true) {
  const msg = "hi";
  console.log(msg);
}

L’affichage fonctionne à l’intérieur du bloc. Ajouter console.log(msg); après celui-ci provoque une ReferenceError, car ce code extérieur ne peut pas accéder à cette déclaration. Une autre déclaration extérieure portant le même nom désignerait une variable différente.

Les paramètres et les variables à l’intérieur d’une fonction sont locaux à celle-ci. Dans function f() { let temp = 1; }, le code extérieur ne peut pas lire temp. Deux fonctions peuvent chacune avoir une variable locale total sans la partager. Chaque appel commence avec de nouvelles variables locales ; une fonction imbriquée renvoyée peut ensuite en conserver l’accès grâce à une fermeture.

Lis les anciennes déclarations avec var
DéclarationLimite de portée
let ou const dans un blocCe bloc
var dans une fonctionLa fonction qui l’entoure, même si la déclaration est écrite dans un bloc intérieur
Déclaration au niveau supérieur dans un script classiqueLa portée globale du script
Déclaration au niveau supérieur dans un moduleCe module
function test() {
  if (true) {
    var x = 1;
  }
  return x;
}

test() renvoie 1 parce que var ignore la limite du bloc if. Le remplacer par let x = 1; fait échouer le retour : le x du bloc n’est pas disponible à cet endroit. De même, for (let i = 0; i < 3; i++) {} garde i dans la boucle, tandis qu’un var i reste disponible dans la fonction ou le script qui l’entoure après la boucle et vaut 3.

Cherche vers l’extérieur depuis l’endroit où la fonction est écrite

Les portées s’imbriquent. Une fonction intérieure peut utiliser les noms des portées qui l’entourent, mais le code extérieur ne peut pas chercher dans les variables locales d’une fonction intérieure. C’est la portée lexicale : l’endroit où le code est écrit détermine les noms disponibles.

const level = "global";
function show() {
  return level;
}
function run() {
  const level = "local";
  return show();
}

run() renvoie « global ». show a été définie en dehors de run, donc la portée qui l’entoure contient le level extérieur. L’appeler depuis run ne lui donne pas accès au level local de la fonction appelante.

Gère volontairement l’état partagé

Une variable de niveau supérieur dans un script classique est globale et les fonctions de ce script peuvent y accéder. Les variables globales partagées peuvent amener des tâches indépendantes à agir les unes sur les autres ; les scripts d’une même page peuvent aussi entrer en conflit sur les noms. Transmettre des entrées et renvoyer des sorties rend les dépendances visibles.

Déclare chaque variable. En mode strict, count = 5; provoque une ReferenceError si aucune déclaration accessible n’existe. Sans mode strict, une telle affectation peut créer une variable globale par accident. Un script peut activer le mode strict avec "use strict"; à son début ; les modules l’activent automatiquement. Privilégie const pour les valeurs qui ne sont pas réaffectées et let lorsqu’une réaffectation est nécessaire.

Points clés

  • let et const respectent les limites du bloc ; var respecte les limites de la fonction qui l’entoure.
  • Les paramètres et les variables locales d’une fonction ne sont pas disponibles pour le code extérieur.
  • La portée lexicale dépend de l’endroit où une fonction est définie, et non de l’endroit où elle est appelée.
  • Les variables de niveau supérieur d’un module appartiennent à ce module.
  • Déclare les noms explicitement pour éviter les affectations globales accidentelles.

3.2 Détermine à quelle variable un nom fait référence

Un même nom peut apparaître dans plusieurs portées. JavaScript trouve la déclaration pertinente en cherchant vers l’extérieur à partir du code courant et en s’arrêtant à la première correspondance.

Suis la chaîne de portées
let x = 1;
function f() {
  let x = 2;
  return x;
}

f() renvoie 2. La déclaration locale masque le x extérieur : la recherche s’arrête donc dans f. La valeur extérieure reste égale à 1. Un paramètre peut masquer un nom de la même manière. Si aucune portée de la chaîne ne déclare un nom, sa lecture provoque une ReferenceError.

Une affectation ne déclare pas de nouvelle variable. Avec let count = 0; function add() { count = count + 1; }, add trouve la déclaration extérieure et la modifie. Insérer let change le sens : cela crée un nouveau nom local, qui peut masquer la valeur même que tu voulais lire.

Distingue l’enregistrement de l’initialisation

La remontée des déclarations décrit la manière dont les déclarations sont enregistrées avant l’exécution de leur portée. Leur comportement au début diffère :

DéclarationAvant sa ligne d’initialisation
Déclaration de fonctionSa fonction est disponible
varSa valeur est undefined
let ou constL’accès provoque une ReferenceError

Par exemple, console.log(a); var a = 5; affiche undefined. L’affectation de 5 n’a pas encore eu lieu. console.log(b); let b = 5; échoue en revanche. La période pendant laquelle le nom lexical existe mais n’est pas accessible est sa zone morte temporaire, souvent abrégée en TDZ.

Suis le masquage avant une ligne de déclaration
let n = 10;
function f() {
  console.log(n);
  let n = 20;
}
f();

Le n intérieur masque le nom extérieur dans tout le corps de la fonction, y compris avant la ligne où la déclaration est écrite. À console.log(n), ce nom intérieur est encore dans sa zone morte temporaire : l’appel provoque donc une ReferenceError. JavaScript n’ignore pas une déclaration locale non initialisée pour utiliser la valeur extérieure 10.

Le même problème apparaît dans let count = count + 1; à l’intérieur de add. Le membre de droite lit le nouveau count local avant son initialisation. Si l’intention est de mettre à jour un compteur extérieur, utilise une affectation sans nouvelle déclaration. Si l’intention est de calculer une valeur distincte, donne-lui un nom différent et lis explicitement le compteur extérieur.

Distingue la réaffectation de la mutation

let et const ne peuvent pas déclarer à nouveau le même nom dans une portée ; cela provoque une SyntaxError. Une portée intérieure peut déclarer son propre nom : c’est le masquage. var autorise les déclarations répétées dans sa portée, ce qui rend la réutilisation accidentelle d’un nom plus difficile à remarquer.

const empêche la réaffectation de sa variable. Il ne fige pas un tableau :

const list = [];
list.push(1);

La référence stockée dans list reste la même tandis que le tableau devient [1]. list = []; tenterait de remplacer la référence stockée et échouerait.

Place une déclaration dans la plus petite portée où elle est nécessaire. Des noms distincts pour des tâches distinctes réduisent le besoin de suivre mentalement le masquage, et initialiser les variables avant leur utilisation évite les erreurs liées à la zone morte temporaire.

Points clés

  • La recherche d’un nom s’arrête à la déclaration la plus proche dans les portées englobantes.
  • Une déclaration locale masque un nom extérieur même avant son initialisation.
  • var vaut initialement undefined ; let et const sont inaccessibles dans leur zone morte temporaire.
  • Une affectation met à jour une liaison existante ; une déclaration en crée une.
  • const empêche la réaffectation, mais le contenu d’un tableau peut toujours changer.
  • Une nouvelle déclaration dans une même portée diffère du masquage dans une portée imbriquée.
4

Utilise des fermetures pour donner aux fonctions leur propre mémoire

Une fonction renvoyée peut conserver l’accès aux variables qui entourent sa définition. Ce lien conservé donne une mémoire à un compteur et permet à une fabrique de construire des fonctions avec leurs propres réglages. Tu vas suivre des appels distincts d’une fabrique, un état partagé et des modifications ultérieures de variables capturées, puis utiliser les mêmes règles pour expliquer les fonctions créées dans une boucle. L’état privé découle de la portée lexicale ordinaire, même après le retour de l’appel extérieur.

4.1 Explique ce qu’une fermeture conserve en mémoire

Une fonction conserve un lien vers la portée où elle a été créée. La fonction et cet accès conservé forment une fermeture. Ce lien devient particulièrement utile lorsqu’une fonction imbriquée est renvoyée puis appelée après la fin de son appel extérieur.

Donne une mémoire à une fonction renvoyée
function makeCounter() {
  let count = 0;
  return function () {
    count = count + 1;
    return count;
  };
}
const counter = makeCounter();

L’appel de makeCounter crée count, crée une fonction intérieure, puis renvoie cette fonction. Il n’exécute pas encore le corps intérieur. counter contient maintenant la valeur de la fonction. Son premier appel fait passer le count conservé de 0 à 1 et renvoie 1. Son appel suivant donne à la même variable la valeur 2 et renvoie 2.

Le cadre de pile de l’appel extérieur s’est terminé, mais la variable capturée reste accessible. Une variable locale qui n’a plus aucune utilisation accessible peut être libérée ; ici, la fonction intérieure appelable en a encore besoin. L’accès par la fermeture subsiste après un retour sans rendre la variable globale.

Crée des mémoires indépendantes avec des appels distincts
const a = makeCounter();
const b = makeCounter();
a();
a();
b();

Les résultats sont 1, 2 et 1. Chaque appel de la fabrique a créé un count différent. Les deux fonctions renvoyées par des appels distincts ont le même code, mais des environnements conservés différents.

Copier une référence à une fonction renvoyée fonctionne autrement. Avec const alias = a;, alias() utilise le compteur existant de a ; il n’appelle pas makeCounter et ne crée pas un autre environnement.

Conserve les variables, et non des instantanés
let greeting = "Hi";
const say = () => greeting;
greeting = "Hello";

say() renvoie « Hello ». La fermeture lit la variable lorsqu’elle s’exécute : une mise à jour ultérieure est donc visible. Elle ne stocke pas une copie figée de « Hi » au moment de sa création.

Le code extérieur ne peut pas accéder directement au count local, et counter.count vaut undefined. Seul le code qui a accès à cet environnement lexical peut le lire ou le mettre à jour. Appeler le compteur depuis une autre fonction ne change pas le compteur qu’il utilise.

Partage un état au sein d’un même appel extérieur
function makeWallet() {
  let balance = 0;
  return [
    function deposit(n) { balance += n; return balance; },
    function getBalance() { return balance; }
  ];
}
const [deposit, getBalance] = makeWallet();
deposit(50);
deposit(20);

getBalance() renvoie 70 parce que les deux fonctions renvoyées ont été créées lors du même appel et font référence au même balance. Un autre appel de makeWallet() crée un solde distinct.

Points clés

  • Une fermeture conserve l’accès à la portée où sa fonction a été créée.
  • Une variable capturée peut rester utilisable après le retour de son appel extérieur.
  • Des appels distincts d’une fabrique créent des environnements distincts.
  • Les fermetures lisent les valeurs actuelles des variables, et non des instantanés pris à leur création.
  • Les fonctions issues d’un même appel extérieur peuvent partager un état privé.

4.2 Utilise des fermetures pour créer des fabriques de fonctions et conserver un état privé

Une fabrique de fonctions utilise l’accès conservé par une fermeture pour créer des fonctions dotées de leurs propres réglages ou de leur propre état. Le code appelant fournit la configuration une fois, puis utilise la fonction renvoyée à plusieurs reprises.

Configure une fonction avec un paramètre
function makeMultiplier(factor) {
  return (n) => n * factor;
}
const double = makeMultiplier(2);
const triple = makeMultiplier(3);

double(5) renvoie 10 et triple(5) renvoie 15. Chaque fonction fléchée renvoyée conserve le factor de son propre appel de fabrique. La fonction extérieure configure le comportement ; la fonction intérieure effectue le travail répété.

La forme compacte est const makeMultiplier = (factor) => (n) => n * factor;. Deux flèches signifient deux créations de fonctions, et non deux calculs consécutifs sur un même nombre. makeMultiplier(4)(5) renvoie d’abord une fonction configurée avec 4, puis l’appelle avec 5 pour obtenir 20.

Fais respecter une règle autour d’un état privé
function makeLimiter(max) {
  let used = 0;
  return function () {
    if (used >= max) {
      return false;
    }
    used = used + 1;
    return true;
  };
}
const tryLogin = makeLimiter(3);

Les trois premiers appels renvoient true et incrémentent used. Le quatrième renvoie false avant l’incrémentation. used est locale à l’appel de la fabrique : le code extérieur ne peut donc pas la réinitialiser sous ce nom. La fonction renvoyée contrôle les modifications possibles. Un autre limiteur aurait sa propre variable used et son propre maximum.

Analyse les fonctions créées dans des boucles
const fns = [];
for (var i = 0; i < 3; i++) {
  fns.push(() => i);
}

La boucle crée trois fonctions, mais un seul var i. Après la boucle, cette variable vaut 3. Appeler n’importe quelle fonction stockée renvoie alors 3 parce que chaque fermeture lit la même liaison courante. Créer une fonction n’évalue pas son corps et ne prend pas un instantané du i courant.

Remplacer l’en-tête par let i = 0 donne à la boucle une liaison distincte pour chaque itération. Les fonctions stockées renvoient alors 0, 1 et 2. La même distinction explique l’affichage différé : une fonction de rappel setTimeout qui lit var i après la boucle voit la valeur finale, tandis que la version avec let conserve la valeur de chaque itération.

Reconnais une expression immédiatement invoquée

Le code ancien crée souvent une portée de fonction privée et l’exécute immédiatement :

(function () {
  var hidden = 1;
  console.log(hidden);
})();

C’est une expression de fonction immédiatement invoquée, ou IIFE. Les parenthèses extérieures produisent une expression de fonction ; les parenthèses finales l’appellent. hidden appartient à cette fonction et reste ainsi hors de la portée globale environnante. C’est un motif courant dans le code écrit avant les déclarations à portée de bloc et les modules.

L’accès conservé a aussi un effet sur la mémoire. Une fermeture appelable qui a besoin d’un grand tableau garde ces données accessibles. Lorsque la fonction et ses données capturées ne sont plus accessibles, elles peuvent être libérées. Stocke les fermetures de longue durée de manière réfléchie lorsque leur mémoire fait partie de la tâche.

Points clés

  • Les fabriques renvoient des fonctions configurées par leurs arguments.
  • Les variables privées peuvent être modifiées par les opérations renvoyées.
  • Les fermetures d’une boucle avec var partagent une liaison ; les itérations d’une boucle avec let reçoivent des liaisons distinctes.
  • Une IIFE crée une portée de fonction et l’exécute immédiatement.
  • Les fermetures accessibles gardent accessibles les données capturées dont elles ont besoin.
5

Passe des fonctions à d’autres fonctions

Transmettre une fonction permet au code appelant de choisir une partie du comportement d’une autre fonction. Tu vas examiner comment les fonctions qui reçoivent des fonctions de rappel les invoquent, quels arguments elles leur fournissent et comment elles utilisent leur résultat. Les méthodes de tableau que tu connais deviennent alors des exemples de schémas d’ordre supérieur réutilisables. Enfin, des fonctions renvoyées envelopperont des appels, relieront des sorties à des entrées ou conserveront certains arguments pour une utilisation ultérieure, en combinant les valeurs de fonction et l’accès conservé par une fermeture.

5.1 Passe une fonction de rappel à une fonction

Une fonction de rappel est une fonction fournie comme argument pour qu’une autre fonction l’appelle. Elle permet à la fonction qui la reçoit de gérer la tâche générale tandis que le code appelant fournit une action ou un test particulier.

Passe une action à une boucle
function repeat(times, action) {
  for (let i = 0; i < times; i++) {
    action(i);
  }
}
repeat(3, (i) => console.log(i));

repeat contient la boucle et choisit les valeurs 0, 1 et 2. La fonction fléchée définit quoi faire de chaque valeur : l’afficher. Chaque action(i) appelle la fonction fournie avec le numéro de l’itération.

Tu peux transmettre une fonction existante ou en écrire une directement sur place. repeat(2, sayHi) transmet la fonction nommée. repeat(2, (i) => console.log("Round " + (i + 1))) affiche « Round 1 » et « Round 2 ». Une fonction de rappel peut ignorer les arguments dont elle n’a pas besoin.

Transmets la valeur sans appeler la fonction trop tôt

repeat(3, sayHi()) évalue sayHi() pendant la préparation des arguments. Si sayHi ne fait qu’afficher du texte, sa valeur de retour est undefined : repeat reçoit donc cette valeur comme action. L’appel ultérieur action(i) échoue avec une TypeError parce que undefined n’est pas appelable.

Utilise repeat(3, sayHi) pour transmettre la fonction. Si l’appel final nécessite des arguments choisis, transmets une fonction enveloppante comme () => sayHi() afin que l’appel ait lieu dans le corps de la fonction de rappel. La création et l’invocation d’une fonction sont deux étapes distinctes.

Vérifie les arguments fournis par la fonction qui reçoit la fonction de rappel

Les fonctions de rappel des tableaux reçoivent souvent plusieurs arguments : l’élément, l’indice et le tableau entier. Transmettre une fonction existante n’est sûr que si ces entrées correspondent au sens de ses paramètres.

["1", "2", "3"].map(parseInt);

Cela renvoie [1, NaN, NaN]. parseInt accepte un deuxième argument pour la base de numération : l’indice du tableau change donc son comportement. Utilise ["1", "2", "3"].map((s) => parseInt(s, 10)) pour choisir explicitement la base 10, ou .map(Number) pour convertir ces chaînes.

Renvoie une réponse à la fonction qui reçoit la fonction de rappel
function countIf(arr, test) {
  let n = 0;
  for (const x of arr) {
    if (test(x)) {
      n++;
    }
  }
  return n;
}

countIf([3, 8, 12, 5], (x) => x > 4) renvoie 3. La fonction de rappel répond à une question pour chaque élément ; countIf utilise chaque réponse pour décider s’il faut incrémenter le compteur. Compare avec repeat, dont la boucle ignore la valeur de retour de la fonction de rappel. Le code ou la documentation de la fonction qui reçoit la fonction de rappel indique les arguments et le rôle du résultat.

Les fonctions de rappel peuvent s’exécuter immédiatement ou plus tard. repeat et les méthodes de tableau les appellent de manière synchrone avant de renvoyer leur résultat. setTimeout(sayHi, 2000) en planifie une pour plus tard tandis que le code suivant continue immédiatement. L’expression « fonction de rappel » décrit la manière dont une fonction est fournie, et non le moment où elle doit s’exécuter.

Points clés

  • Une fonction de rappel est transmise pour qu’une autre fonction l’appelle.
  • La fonction qui reçoit la fonction de rappel contrôle ses arguments et décide si son résultat est utilisé.
  • Ajouter les parenthèses d’appel trop tôt peut transmettre un résultat au lieu d’une fonction.
  • Les arguments d’une fonction de rappel de tableau peuvent changer le comportement d’une fonction existante.
  • Les fonctions de rappel peuvent être synchrones ou différées.

5.2 Utilise et écris des fonctions d’ordre supérieur

Une fonction d’ordre supérieur accepte une fonction, renvoie une fonction, ou les deux. La valeur de fonction fournit un comportement, tandis que la fonction d’ordre supérieur gère un schéma réutilisable.

Écris le schéma une seule fois
function myMap(arr, transform) {
  const result = [];
  for (const item of arr) {
    result.push(transform(item));
  }
  return result;
}

myMap([1, 2, 3], (n) => n * n) renvoie [1, 4, 9]. La boucle et la construction du tableau de sortie restent les mêmes ; la fonction de rappel décide comment chaque élément change. Un filtre correspondant ajoute un élément uniquement lorsque test(item) est une valeur vraie. Avec [4, 7, 10, 3] et (n) => n % 2 === 0, ce schéma conserve [4, 10].

Choisis le contrat de fonction de rappel dont tu as besoin
MéthodeRôle de la fonction de rappelRésultat de la méthode
mapRenvoyer chaque valeur transforméeUn nouveau tableau de même longueur
filterRenvoyer une valeur vraie pour les éléments à conserverUn nouveau tableau d’éléments sélectionnés
findTester si un élément correspondPremière correspondance, ou undefined
forEachEffectuer une action pour chaque élémentundefined
reduceRenvoyer l’accumulateur suivantL’accumulateur final

map, filter et find ne modifient pas elles-mêmes le tableau d’entrée, mais les fonctions de rappel peuvent tout de même le modifier. Le fait qu’une méthode renvoie un nouveau tableau ne rend pas pure toute fonction de rappel fournie.

Fais évoluer un résultat par réduction
[5, 10, 15].reduce((total, n) => total + n, 0);

L’accumulateur initial vaut 0. La fonction de rappel renvoie 5 pour le premier élément, 15 pour le deuxième et 30 pour le troisième. Chaque valeur renvoyée devient le total de l’appel suivant. La méthode renvoie 30 après le dernier élément. Un tableau vide sans accumulateur initial fait que reduce provoque une TypeError ; une valeur initiale explicite définit aussi un résultat utile pour une entrée vide.

Le renvoi de tableaux rend le chaînage possible. [3, 8, 12, 5].filter((n) => n > 4).map((n) => n * 2) conserve d’abord [8, 12, 5], puis le transforme en [16, 24, 10]. Lis la chaîne dans l’ordre d’exécution, de gauche à droite.

Fournis une règle de tri numérique

Sans comparateur, sort compare les éléments comme des chaînes de caractères. [10, 9, 1].sort() produit donc [1, 10, 9]. Pour un ordre numérique croissant, utilise .sort((a, b) => a - b). Une valeur de retour négative place a en premier, une valeur positive place b en premier et zéro laisse les deux éléments équivalents pour le tri. Contrairement à map et filter, sort réorganise son tableau d’entrée.

Vérifie les valeurs renvoyées

[1, 2, 3].map((n) => { n * 2; }) produit [undefined, undefined, undefined] parce que le bloc n’a pas de retour. Utiliser forEach pour construire un nouveau résultat par affectation échoue aussi si tu attends que la méthode elle-même renvoie un tableau. Choisis map pour une transformation et forEach pour les actions dont les sorties n’ont pas besoin d’être regroupées.

Une méthode d’ordre supérieur exprime clairement un schéma connu. Une simple boucle reste utile lorsque le traitement a besoin de break ou ne correspond pas au contrat de la méthode.

Points clés

  • Les fonctions d’ordre supérieur reçoivent des fonctions, en renvoient ou font les deux.
  • map, filter et find utilisent les résultats des fonctions de rappel de différentes manières.
  • forEach renvoie undefined ; reduce renvoie l’accumulateur final.
  • Une fonction de rappel de réduction doit renvoyer l’accumulateur suivant.
  • Le tri numérique nécessite un comparateur et modifie le tableau d’origine.
  • Une méthode qui renvoie un nouveau tableau peut tout de même exécuter des fonctions de rappel avec des effets de bord.

5.3 Construis de nouvelles fonctions à partir de fonctions existantes

Une fonction peut renvoyer une nouvelle fonction qui conserve une fonction existante en mémoire. Les fonctions enveloppantes, la composition et l’application partielle utilisent ce schéma pour adapter un comportement sans copier le corps de la fonction d’origine.

Enveloppe un appel et préserve son résultat
function logged(fn) {
  return (...args) => {
    console.log("Calling with", args);
    const result = fn(...args);
    console.log("Result", result);
    return result;
  };
}
const add = (a, b) => a + b;

logged(add) crée une fonction qui conserve add sous le nom fn. Appeler logged(add)(2, 3) regroupe les arguments, les transmet à add, affiche la valeur renvoyée et renvoie 5. Le reste regroupe les entrées de la fonction enveloppante ; la décomposition les transmet. Le retour final garde la sortie disponible pour les calculs ultérieurs.

logged(add(2, 3)) transmet à la place le nombre 5. Appeler ensuite cette fonction enveloppante tente d’appeler 5 et provoque une TypeError. Il y a deux étapes : configurer la fonction enveloppante avec une fonction, puis appeler la fonction renvoyée avec des entrées.

Conserve un état autour d’une opération
function once(fn) {
  let done = false;
  let result;
  return (...args) => {
    if (!done) {
      done = true;
      result = fn(...args);
    }
    return result;
  };
}

Pour une opération qui se termine normalement, le premier appel exécute fn et stocke son résultat. Les appels suivants renvoient cette valeur stockée sans exécuter à nouveau fn, même si leurs arguments diffèrent. Le booléen indique si l’opération a été exécutée ; vérifier si le résultat est une valeur vraie serait incorrect lorsqu’un résultat valide est 0 ou false. Chaque appel de once crée son propre indicateur booléen et son propre résultat stocké.

Transmets un résultat à une autre fonction
const compose = (f, g) => (x) => f(g(x));
const addOne = (n) => n + 1;
const square = (n) => n * n;

compose(square, addOne)(3) exécute d’abord addOne(3), puis élève 4 au carré pour renvoyer 16. compose(addOne, square)(3) élève d’abord 3 au carré, puis ajoute 1 et renvoie 10. La fonction la plus proche de l’entrée s’exécute en premier : l’ordre des arguments de compose compte donc.

Fixe certains arguments à l’avance
function partial(fn, ...fixed) {
  return (...rest) => fn(...fixed, ...rest);
}
const greetWith = (greeting, name) => greeting + ", " + name;
const hello = partial(greetWith, "Hello");

hello("Ana") appelle greetWith("Hello", "Ana") et renvoie « Hello, Ana ». Cette fonction auxiliaire d’application partielle place d’abord les arguments fixés, puis les arguments ultérieurs ; changer cet ordre modifie l’appel sous-jacent.

Points clés

  • Une fonction enveloppante conserve une fonction et ajoute un comportement autour de son appel.
  • Le reste et la décomposition permettent à une fonction enveloppante de transmettre des arguments distincts.
  • Renvoyer le résultat de la fonction enveloppée le garde utilisable par le code appelant.
  • Une fonction enveloppante à exécution unique conserve un indicateur booléen et le premier résultat.
  • compose(f, g) applique g avant f.
  • L’application partielle fixe certains arguments avant des appels ultérieurs.

Fonctions JavaScript : exemples

5 Leçons Interactives

1

Crée, stocke et appelle une fonction

11 étapes
Suis une fonction de salutation à travers les déclarations, les valeurs de fonction et les corps de fonctions fléchées.
  1. 1
    IntroductionDistingue la recette de l’appel

    Une fonction enregistre des instructions afin que plusieurs appels puissent les réutiliser. Sa définition décrit une tâche ; un appel accomplit cette tâche avec des entrées particulières.

    Suis une fonction de salutation sous trois formes : une déclaration, une expression stockée dans une variable et une fonction fléchée. Observe deux détails lorsque la syntaxe change : quand la fonction devient disponible et si son corps renvoie une valeur.

  2. 2
    ExempleDéfinis une salutation
    function greet(name) {
      console.log("Hello, " + name + "!");
    }
    

    Le mot-clé, le nom, la liste de paramètres et le corps forment une déclaration. Rien n’a encore été affiché : la définition enregistre les instructions.

    name est un paramètre dont la valeur viendra d’un appel. Le corps peut être réutilisé parce qu’il décrit comment construire la salutation sans choisir à l’avance le nom d’une personne.

  3. 3
    ExempleExécute les instructions enregistrées
    greet("Amira");
    greet("Li");
    

    Les appels affichent « Hello, Amira! » et « Hello, Li! » sur des lignes distinctes. Chacun exécute à nouveau le même corps avec sa propre entrée.

    L’expression greet seule est la valeur de la fonction. Les parenthèses dans greet("Li") demandent son exécution. Même une fonction sans entrée a besoin de parenthèses d’appel, comme dans sayHi().

  4. 4
    DéfiPrévois le résultat d’un appel anticipé

    Qu’affiche ce script lorsqu’il s’exécute ?

    show();
    function show() { console.log("Ready"); }
    

    ---reveal---

    Il affiche « Ready » une fois. La déclaration est remontée dans sa portée : la fonction est donc disponible dès la première ligne. La remontée n’exécute pas le corps à elle seule : c’est l’appel explicite show() qui le fait. Une ligne contenant uniquement show; lirait la fonction sans rien afficher.

  5. 5
    ExplicationConserve la fonction comme valeur
    const square = function (n) {
      return n * n;
    };
    const alias = square;
    

    L’expression crée une fonction et square la stocke. La deuxième affectation copie sa référence dans alias ; elle ne calcule pas de carré. square(3) et alias(3) renvoient tous deux 9.

    En comparaison, const answer = square(3); appelle la fonction et stocke le nombre renvoyé.

  6. 6
    DéfiRepère le premier échec

    Ce script affiche-t-il 16 ?

    console.log(square(4));
    const square = function (n) { return n * n; };
    

    ---reveal---

    Non. Lire square avant son initialisation avec const provoque une ReferenceError. L’affectation ne s’est pas exécutée : la valeur de fonction créée par l’expression n’est donc pas disponible. Déplace l’appel après l’affectation ou utilise une déclaration de fonction si la fonction doit être appelable plus tôt dans cette portée.

  7. 7
    ExempleUtilise une fonction fléchée à corps concis
    const square = (n) => n * n;
    const add = (a, b) => a + b;
    

    Un corps concis de fonction fléchée renvoie son expression : square(4) renvoie donc 16 et add(2, 3) renvoie 5.

    Un seul paramètre simple peut se passer de parenthèses : n => n * n. Les listes vides, les paramètres multiples, les paramètres par défaut et les paramètres du reste les exigent. Les fonctions fléchées sont des expressions : ces variables const doivent donc toujours être initialisées avant leur utilisation.

  8. 8
    DéfiCorrige un résultat manquant

    Pourquoi add(2, 3) renvoie-t-il undefined, et quelle modification lui fait renvoyer 5 ?

    const add = (a, b) => { a + b; };
    

    ---reveal---

    Les accolades ouvrent un bloc : l’expression est donc évaluée, mais pas renvoyée. Écris (a, b) => { return a + b; }, ou retire les accolades pour utiliser (a, b) => a + b. Les deux corrections renvoient la somme. Ajouter simplement un point-virgule après l’affectation ne change pas ce que renvoie le corps.

  9. 9
    ConseilRenvoie une expression d’objet
    const makePoint = (x, y) => ({ x: x, y: y });
    

    Les parenthèses font du littéral d’objet une expression renvoyée par le corps concis. Une accolade ouvrante sans parenthèses ouvrirait un bloc.

    Les fonctions fléchées n’ont pas leur propre this ni leur propre arguments, et elles ne peuvent pas servir de constructeurs. La forme courte convient bien aux calculs simples, mais ces différences comptent lors de la conversion d’autres types de fonctions.

  10. 10
    DéfiSuis une fonction et son autre nom

    Que renvoie copy(5) ?

    const adjust = (n) => { return n + 2; };
    const copy = adjust;
    

    ---reveal---

    Il renvoie 7. Le bloc de la fonction fléchée contient un retour explicite et copy contient la même fonction appelable que adjust. L’affectation n’a pas appelé la fonction ni stocké de résultat numérique. Remplacer const copy = adjust; par const copy = adjust(5); stockerait 7, qui n’est pas appelable.

  11. 11
    RécapitulatifLis l’opération de chaque ligne

    Une déclaration crée une tâche nommée disponible dès le début de sa portée. Une expression crée une valeur de fonction lorsque l’exécution l’atteint. Le corps concis d’une fonction fléchée renvoie automatiquement une valeur ; son corps de bloc nécessite return.

    Lorsque tu suis du code, distingue une définition de fonction, l’affectation d’une référence et un appel. Ce sont des opérations différentes, même lorsqu’elles utilisent le même nom.

2

Suis les entrées, les sorties et les appels en attente

16 étapes
Fais correspondre les arguments, suis les valeurs renvoyées et remonte un court calcul récursif.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionSuis ce qui entre dans un appel et ce qui en sort
  2. 2
    ExempleFais correspondre les arguments selon leur position
  3. 3
    ExempleDistingue la mutation de la réaffectation
  4. 4
    DéfiConserve l’entrée d’origine
  5. 5
    ExplicationLa valeur par défaut s’applique à undefined
  6. 6
    ExempleRegroupe, puis décompose
  7. 7
    DéfiUtilise une valeur par défaut avec le reste
  8. 8
    ExempleRenvoie le nombre dont le code appelant a besoin
  9. 9
    ExempleArrête une branche avec un retour anticipé
  10. 10
    DéfiÉvalue de l’intérieur vers l’extérieur
  11. 11
    ExempleGarde en mémoire l’appelant inachevé
  12. 12
    ExplicationDonne à la récursivité un chemin d’arrêt
  13. 13
    ExempleRemonte les produits en attente
  14. 14
    DéfiCorrige une borne de récursivité
  15. 15
    LienLis un échec à travers la pile
  16. 16
    RécapitulatifSuis une valeur à chaque étape
3

Trouve la déclaration associée à un nom

10 étapes
Suis les limites des blocs, la recherche lexicale et le moment de l’initialisation.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionDemande-toi où le nom appartient
  2. 2
    ExempleCompare les limites de bloc et de fonction
  3. 3
    ExempleUtilise l’emplacement de la définition
  4. 4
    DéfiSuis une valeur locale et une valeur extérieure
  5. 5
    ExplicationArrête-toi à la déclaration la plus proche
  6. 6
    Point cléEnregistré ne signifie pas initialisé
  7. 7
    DéfiPrévois la lecture d’un nom masqué
  8. 8
    ConseilDistingue la réaffectation de la mutation
  9. 9
    DéfiCombine une fonction de rappel et le moment de la recherche
  10. 10
    RécapitulatifSuis l’emplacement avant la valeur
4

Donne aux fonctions renvoyées leur propre mémoire

11 étapes
Suis les états partagés et indépendants des fermetures, puis examine les fonctions créées dans une boucle.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionConserve l’accès après un retour
  2. 2
    ExempleCrée un compteur sans l’appeler
  3. 3
    ExempleMets à jour la variable conservée
  4. 4
    DéfiCompare des compteurs indépendants
  5. 5
    Point cléConserve la liaison, et non un instantané
  6. 6
    ExempleCrée un calcul configuré
  7. 7
    ExempleConserve un compteur d’utilisations privé
  8. 8
    DéfiExplique trois résultats égaux
  9. 9
    LienReconnais une portée privée dans le code ancien
  10. 10
    DéfiPartage une opération configurée
  11. 11
    RécapitulatifSuis le nombre d’environnements existants
5

Transmets un comportement et construis des fonctions adaptées

15 étapes
Suis les arguments des fonctions de rappel, les résultats des méthodes de tableau et les fonctions qui renvoient des fonctions configurées.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionLaisse une fonction fournir le comportement qui change
  2. 2
    ExempleAppelle l’action fournie
  3. 3
    DéfiUtilise le résultat d’une fonction de rappel
  4. 4
    ConseilExamine tous les arguments de la fonction de rappel
  5. 5
    ExempleÉcris un schéma de transformation
  6. 6
    ExplicationChoisis la forme du résultat
  7. 7
    DéfiSuis une sélection et une transformation
  8. 8
    Point cléChoisis explicitement l’ordre numérique
  9. 9
    ExempleEnveloppe et transmets un appel
  10. 10
    ExplicationGarde en mémoire si un appel a été exécuté
  11. 11
    ExempleCompose de l’intérieur vers l’extérieur
  12. 12
    ExempleFixe des entrées avant l’appel ultérieur
  13. 13
    DéfiPasse une fonction de rappel configurée
  14. 14
    DéfiCorrige un résultat perdu par une fonction enveloppante
  15. 15
    RécapitulatifVérifie les deux étapes du code d’ordre supérieur

Fonctions JavaScript : QCM

50 Questions Pratiques en 5 séries

Série 1 : Choisis les entrées et suis l’état conservé10 Questions Pratiques

Question 1 sur 10

Que se passe-t-il lorsque ce script s’exécute ?

announce();
function announce() { console.log("Open"); }
  1. Il provoque une ReferenceError.
  2. Il affiche undefined une fois.
  3. Il affiche « Open » une fois.
  4. Il provoque une TypeError.
Afficher la réponseMasquer la réponse
Réponse : C
La déclaration est remontée dans la portée du script : announce est donc déjà une fonction lorsque la première ligne l’appelle. Son corps affiche « Open » une fois. Le moment de l’initialisation d’une expression de fonction stockée dans const serait différent, mais ce code utilise une déclaration.

Question 2 sur 10

Comment une fonction fléchée peut-elle renvoyer un objet dont la propriété value est égale à son entrée n ?
  1. (n) => ({ value: n })
  2. (n) => { return; value: n; }
  3. (n) => (value = n)
  4. (n) => { value: n }
Afficher la réponseMasquer la réponse
Réponse : A
Les parenthèses font de { value: n } une expression d’objet, que le corps concis de la fonction fléchée renvoie. Sans ces parenthèses, les accolades ouvrent un bloc et value: n est interprété comme une instruction étiquetée : aucun objet n’est alors renvoyé. Un simple return; renvoie aussi undefined.

Question 3 sur 10

Que renvoie l’appel ?

function combine(first, ...rest) {
  return first + rest.length;
}
const values = [8, 2, 6];
combine(...values);
  1. 16
  2. 8
  3. 11
  4. 10
Afficher la réponseMasquer la réponse
Réponse : D
La décomposition transmet trois arguments distincts. Le paramètre fixe reçoit 8 et le reste regroupe [2, 6], dont la longueur est de 2 : la fonction renvoie donc 10. Compter les trois valeurs dans rest donnerait 11, mais le premier argument a déjà été affecté à first.

Question 4 sur 10

Que renvoie guarded(0) ?

function guarded(n) {
  if (n === 0) { return "empty"; }
  return "filled";
}
  1. "filled"
  2. "empty"
  3. ["empty", "filled"]
  4. undefined
Afficher la réponseMasquer la réponse
Réponse : B
La condition est vraie pour 0 : le premier retour termine donc immédiatement l’appel avec « empty ». L’exécution ne se poursuit pas jusqu’au retour suivant. Une fonction renvoie une valeur pour un appel donné ; deux instructions de retour décrivent des chemins possibles différents, et non une liste de sorties regroupées.

Question 5 sur 10

Que renvoie totalDown(3) ?

function totalDown(n) {
  if (n === 0) { return 0; }
  return n + totalDown(n - 1);
}
  1. 0
  2. 6
  3. 9
  4. 3
Afficher la réponseMasquer la réponse
Réponse : B
Les appels atteignent totalDown(0), qui renvoie 0. Les appels en attente renvoient ensuite 1, 3 et 6. Le retour du cas de base ne remplace pas le résultat de chaque appel par 0 ; chaque cadre en attente possède toujours son propre n et doit terminer son addition.

Question 6 sur 10

Que se passe-t-il lorsque read() est appelée ?

let label = "outer";
function read() {
  return label;
  let label = "inner";
}
  1. Elle renvoie la chaîne « inner ».
  2. Elle renvoie la chaîne « outer ».
  3. Elle provoque une ReferenceError.
  4. Elle renvoie la valeur undefined.
Afficher la réponseMasquer la réponse
Réponse : C
La déclaration locale masque le label extérieur dans toute la fonction read, y compris au niveau du retour situé avant elle. Cette variable locale n’est pas encore initialisée : sa lecture provoque donc une ReferenceError. L’affectation inaccessible ne conduit pas JavaScript à ignorer la déclaration locale pour utiliser la chaîne extérieure.

Question 7 sur 10

Que renvoie l’appel final ?

let word = "first";
const read = () => word;
word = "second";
function run() {
  const word = "third";
  return read();
}
run();
  1. "second"
  2. undefined
  3. "first"
  4. "third"
Afficher la réponseMasquer la réponse
Réponse : A
read capture le word de niveau supérieur, dont la valeur actuelle est « second ». Elle ne conserve pas une copie figée de « first », et l’appeler depuis run ne redirige pas sa recherche vers la valeur locale « third » de cette fonction appelante. L’emplacement de la définition et l’affectation ultérieure comptent tous les deux.

Question 8 sur 10

Quel tableau l’expression finale produit-elle ?

const readers = [];
for (let i = 1; i <= 3; i++) {
  let value = i;
  readers.push(() => value);
  value += 10;
}
readers.map((read) => read());
  1. [13, 13, 13]
  2. [1, 2, 3]
  3. [14, 14, 14]
  4. [11, 12, 13]
Afficher la réponseMasquer la réponse
Réponse : D
Chaque itération crée son propre value, et sa fonction conserve cette liaison. L’addition ultérieure dans cette même itération donne à la valeur que la fonction lira 11, 12 ou 13. [1, 2, 3] reviendrait à traiter la création de la fermeture comme un instantané et à ignorer ces mises à jour ultérieures.

Question 9 sur 10

Que se passe-t-il lorsque la dernière ligne s’exécute ?

function speak() { console.log("Hi"); }
function twice(action) { action(); action(); }
twice(speak());
  1. Elle affiche « Hi » une fois, puis provoque une TypeError.
  2. Elle provoque une TypeError avant tout affichage.
  3. Elle affiche « Hi » deux fois, puis se termine normalement.
  4. Elle affiche « Hi » trois fois, puis se termine normalement.
Afficher la réponseMasquer la réponse
Réponse : A
La préparation de l’argument appelle immédiatement speak : « Hi » s’affiche donc une fois. Sa valeur de retour est undefined, qui devient action ; la première tentative d’appel de action() provoque alors une TypeError. Transmettre speak sans parenthèses d’appel permettrait à twice de l’invoquer deux fois.

Question 10 sur 10

Quel est le résultat final ?

const compose = (f, g) => (x) => f(g(x));
const subtract = (n) => n - 2;
const triple = (n) => n * 3;
const first = compose(triple, subtract);
const second = compose(subtract, triple);
first(second(4));
  1. 18
  2. 28
  3. 24
  4. 30
Afficher la réponseMasquer la réponse
Réponse : C
second(4) triple 4 et soustrait 2, ce qui renvoie 10. Cette valeur devient l’entrée de first, qui soustrait 2 et triple 8, ce qui renvoie 24. Un résultat de 18 applique first et second dans l’ordre extérieur inverse ; chaque composition doit aussi respecter son propre ordre d’appel, de l’intérieur vers l’extérieur.
Série 2 : Relie les appels, la portée et les fonctions de rappel10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Que se passe-t-il lorsque ce script s’exécute ?

const saved = build;
const build = function () { return 9; };
console.log(saved());
  1. Il provoque une ReferenceError à la première ligne.
  2. Il provoque une TypeError à la dernière ligne.
  3. Il affiche undefined à la dernière ligne.
  4. Il affiche 9 une fois l’affectation terminée.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Quelle valeur est affectée à out ?

const describe = (n) => {
  const doubled = n * 2;
  return doubled + 1;
};
const out = describe(6);
  1. undefined
  2. 7
  3. 13
  4. 12
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Que valent items et answer après ce code ?

const items = [5];
function change(list) {
  list.push(8);
  list = [1];
  return list;
}
const answer = change(items);
  1. items vaut [5, 8] ; answer vaut [5, 8].
  2. items vaut [5] ; answer vaut [1].
  3. items vaut [1] ; answer vaut [1].
  4. items vaut [5, 8] ; answer vaut [1].
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Que renvoie countLeaves([0, [[], 2], [[3], 4]]) ?

function countLeaves(list) {
  let count = 0;
  for (const item of list) {
    if (Array.isArray(item)) {
      count += countLeaves(item);
    } else {
      count++;
    }
  }
  return count;
}
  1. 6
  2. 4
  3. 3
  4. 5
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Que renvoie readValue() ?

function readValue() {
  if (true) { var value = 14; }
  return value;
}
  1. 14
  2. undefined
  3. Elle provoque une ReferenceError.
  4. Elle provoque une TypeError.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Quelles sont les deux valeurs affichées ?

let count = 2;
function update() {
  let count = 7;
  count += 1;
  return count;
}
console.log(update());
console.log(count);
  1. 3, 3
  2. 7, 2
  3. 8, 2
  4. 8, 8
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Quelles valeurs les trois derniers appels renvoient-ils ?

function makeCounter(start) {
  let n = start;
  return () => { n++; return n; };
}
const a = makeCounter(5);
const alias = a;
const b = makeCounter(5);
a();
alias();
b();
  1. 5, 6, 5
  2. 6, 7, 6
  3. 6, 7, 8
  4. 6, 6, 6
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Que renvoie scale(7) ?

const makeScale = (factor) => (n) => n * factor;
const scale = makeScale(4);
  1. 7
  2. 11
  3. Une nouvelle fonction.
  4. 28
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Que valent ensuite values et first ?

const values = [12, 3, 20];
const first = values.sort((a, b) => a - b)[0];
  1. values vaut [12, 3, 20] ; first vaut 3.
  2. values vaut [3, 12, 20] ; first vaut 3.
  3. values vaut [20, 12, 3] ; first vaut 20.
  4. values vaut [12, 20, 3] ; first vaut 12.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Que renvoient les appels read(0) et read(9), dans l’ordre ?

function once(fn) {
  let done = false;
  let result;
  return (...args) => {
    if (!done) {
      done = true;
      result = fn(...args);
    }
    return result;
  };
}
const read = once((n) => n * 2);
  1. undefined, 18
  2. 0, 18
  3. 0, 0
  4. 0, undefined
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 3 : Lis des fonctions et suis leurs valeurs10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Étant donné function showLabel() { console.log("Ready"); }, quelle instruction appelle la fonction ?
  1. "showLabel";
  2. showLabel();
  3. showLabel;
  4. const label = showLabel;
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Que contient copy après ce code ?

const triple = function (n) { return n * 3; };
const copy = triple;
  1. La valeur undefined jusqu’à l’appel de copy.
  2. Une fonction distincte dont l’état privé est copié.
  3. Le nombre renvoyé par l’appel de triple(3).
  4. Une référence à la même fonction que triple.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Que renvoie adjust(8) ?

const adjust = (n) => { n - 3; };
  1. undefined
  2. 5
  3. 8
  4. NaN
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Que renvoie difference(12, 5) ?

function difference(first, second) {
  return first - second;
}
  1. 17
  2. undefined
  3. 7
  4. -7
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Que renvoie readLevel(0) ?

function readLevel(level = 40) { return level; }
  1. 40
  2. undefined
  3. null
  4. 0
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Quels sont le nombre affiché et la valeur de result ?

function displayTotal(a, b) { console.log(a + b); }
const result = displayTotal(6, 9);
  1. Affiche 15 ; result vaut 15.
  2. Affiche 15 ; result vaut undefined.
  3. N’affiche rien ; result vaut 15.
  4. Affiche undefined ; result vaut 15.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Que se passe-t-il lorsque getFlag() est appelée ?

function getFlag() {
  if (true) { let flag = "on"; }
  return flag;
}
  1. Elle provoque une ReferenceError.
  2. Elle provoque une TypeError.
  3. Elle renvoie la valeur undefined.
  4. Elle renvoie la chaîne « on ».
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Quelles valeurs les deux appels renvoient-ils, dans l’ordre ?

function makeStep() {
  let value = 4;
  return () => { value += 2; return value; };
}
const step = makeStep();
step();
step();
  1. 4, 6
  2. 8, 10
  3. 6, 8
  4. 6, 6
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Quelle est la suite complète des valeurs affichées ?

function deliver(action) { action(7); }
console.log("start");
deliver((n) => console.log(n));
console.log("end");
  1. "start", 7, "end"
  2. "start", undefined, "end"
  3. "start", "end", 7
  4. 7, "start", "end"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Quelle est la valeur finale de result ?

const values = [2, 7, 4, 9];
const result = values
  .filter((n) => n > 3)
  .map((n) => n - 1)
  .reduce((total, n) => total + n, 5);
  1. 27
  2. 22
  3. 17
  4. 21
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 4 : Analyse le comportement des fonctions dans de petits programmes10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Un script définit function printLine() { console.log("---"); }, puis exécute printline();. Que se passe-t-il ?
  1. L’appel renvoie undefined sans rien afficher.
  2. Une ligne s’affiche et l’exécution continue.
  3. Une TypeError se produit et aucune ligne ne s’affiche.
  4. Une ReferenceError se produit et aucune ligne ne s’affiche.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Que renvoie l’appel final ?

const climb = function step(n) {
  return n === 0 ? 0 : 1 + step(n - 1);
};
const saved = climb;
saved(2);
  1. 0
  2. 2
  3. Il provoque une ReferenceError.
  4. 1
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Que valent data et result à la fin ?

const data = [2, 5];
function extend(list, item) {
  const next = list.concat(item);
  list.push(9);
  return next;
}
const result = extend(data, 7);
result.push(1);
  1. data vaut [2, 5, 9] ; result vaut [2, 5, 7, 1].
  2. data vaut [2, 5, 9, 1] ; result vaut [2, 5, 7, 1].
  3. data vaut [2, 5, 7, 9] ; result vaut [2, 5, 7, 9, 1].
  4. data vaut [2, 5] ; result vaut [2, 5, 7, 9, 1].
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Que renvoie l’appel final ?

function total(base = 4, ...extras) {
  return extras.reduce((sum, n) => sum + n, base);
}
const values = [undefined, 3, 0, 8];
total(...values);
  1. NaN
  2. 11
  3. 15
  4. 19
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Quelle valeur cet appel produit-il ?

function read() {
  return;
}
read();
  1. undefined
  2. null
  3. false
  4. 0
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

L’entrée n est un entier positif ou nul. Par quoi remplacer le retour récursif pour que la fonction compte correctement jusqu’à 0, aussi bien pour les entrées impaires que paires ?

function countDown(n) {
  if (n === 0) { return 0; }
  // recursive return goes here
}
  1. return 1 + countDown(n - 2);
  2. return 1 + countDown(n - 1);
  3. return 1 + countDown(n);
  4. return 1 + countDown(n + 1);
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Que renvoie l’appel final ?

const mode = "shared";
function readMode() { return mode; }
function run() {
  const mode = "local";
  return readMode();
}
run();
  1. Il provoque une ReferenceError.
  2. undefined
  3. "local"
  4. "shared"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Quelles valeurs jobs[0]() et jobs[1]() renvoient-ils après la boucle ?

const jobs = [];
for (var i = 0; i < 2; i++) {
  const offset = i * 10;
  jobs.push(() => offset + i);
}
  1. 12, 12
  2. 0, 10
  3. 2, 12
  4. 0, 11
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Quel résultat cette expression produit-elle ?

["6", "8", "10"].map((text) => parseInt(text, 10));
  1. [6, NaN, NaN]
  2. [6, 8, 10]
  3. [6, NaN, 2]
  4. ["6", "8", "10"]
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Quelles sont les valeurs affichées de out et de seen ?

let seen = 0;
const out = [3, 5].forEach((n) => {
  seen += n;
  return n * 2;
});
console.log(out, seen);
  1. undefined, 8
  2. [6, 10], 8
  3. undefined, 16
  4. [6, 10], 0
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 5 : Combine les fermetures et les fonctions d’ordre supérieur10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Quelle fonction fléchée renvoie la somme de ses deux entrées ?
  1. (a, b) => { console.log(a + b); }
  2. (a, b) => { return a + b; }
  3. (a, b) => { return; a + b; }
  4. (a, b) => { a + b; }
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Combien vaut add("6", 4) * 2 ?

function add(a, b) { return a + b; }
  1. 20
  2. NaN
  3. 128
  4. "6464"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Combien vaut l’expression finale ?

function choose(n) {
  if (n < 0) { return 0; }
  return n + 2;
}
choose(choose(-4));
  1. 2
  2. -2
  3. 0
  4. 4
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Que se passe-t-il lorsque build() est appelée ?

let amount = 6;
function build() {
  const read = () => amount;
  const result = read();
  let amount = 9;
  return result;
}
  1. Elle renvoie le nombre 6.
  2. Elle renvoie le nombre 9.
  3. Elle renvoie la valeur undefined.
  4. Elle provoque une ReferenceError dans read.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Quelles valeurs change(3), read() et otherRead() renvoient-ils ?

function makePair() {
  let n = 1;
  return [
    (step) => { n += step; return n; },
    () => n
  ];
}
const [change, read] = makePair();
const [, otherRead] = makePair();
  1. 4, 1, 1
  2. 4, 4, 4
  3. 3, 3, 1
  4. 4, 4, 1
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Que renvoie l’expression finale ?

function makeLimit(max) {
  let used = 0;
  return () => {
    if (used >= max) { return false; }
    used++;
    return true;
  };
}
const allow = makeLimit(2);
[allow(), allow(), allow()];
  1. [true, true, true]
  2. [true, true, false]
  3. [true, false, false]
  4. [false, false, false]
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Que valent result et calls après ce code ?

let calls = 0;
function choose(values, test) {
  for (const value of values) {
    calls++;
    if (test(value)) { return value; }
  }
  return null;
}
const result = choose([3, 8, 10, 5], (n) => n > 6 && n % 2 === 0);
  1. result vaut 8 ; calls vaut 2.
  2. result vaut [8, 10] ; calls vaut 4.
  3. result vaut 8 ; calls vaut 4.
  4. result vaut 10 ; calls vaut 3.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Que valent ensuite items et out ?

const items = [2, 4, 6];
const out = items.map((n, index, array) => {
  array[index] = n + 1;
  return n * 2;
});
  1. items vaut [4, 8, 12] ; out vaut [3, 5, 7].
  2. items vaut [3, 5, 7] ; out vaut [6, 10, 14].
  3. items vaut [3, 5, 7] ; out vaut [4, 8, 12].
  4. items vaut [2, 4, 6] ; out vaut [4, 8, 12].
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Que renvoie doubleSaved(9) après l’appel précédent indiqué ?

function once(fn) {
  let done = false;
  let saved;
  return (...args) => {
    if (!done) { done = true; saved = fn(...args); }
    return saved;
  };
}
const compose = (f, g) => (x) => f(g(x));
const saved = once((n) => n + 3);
const doubleSaved = compose((n) => n * 2, saved);
saved(4);
doubleSaved(9);
  1. 18
  2. 14
  3. 7
  4. 24
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Quel est le tableau renvoyé ?

const partial = (fn, ...fixed) => (...later) => fn(...fixed, ...later);
const offset = (base, n) => base + n;
const addFive = partial(offset, 5);
const compose = (f, g) => (x) => f(g(x));
const transform = compose((n) => n * n, addFive);
[1, 3].map(transform);
  1. [12, 16]
  2. [6, 14]
  3. [36, 64]
  4. [26, 28]
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Tu bloques sur ton propre exercice ? Aide aux Devoirs

Mots-Clés

66 Mots-Clés, chacun avec sa définition

A

Accumulateur
Un accumulateur est le résultat courant d’une réduction, transmis à la fonction de rappel et remplacé par la valeur qu’elle renvoie à chaque étape.
Une réduction qui calcule une somme à partir de 0 donne successivement à son accumulateur les valeurs 5, 15 et 30 lors du traitement de [5, 10, 15].
Appel de fonction
Un appel de fonction invoque une fonction à l’aide de parenthèses placées après une valeur de fonction, les éventuels arguments étant placés dans ces parenthèses.
Écrire sayHi() exécute son corps, tandis qu’une ligne contenant uniquement sayHi lit la valeur de la fonction.
Application partielle
L’application partielle fixe certains arguments à l’avance et renvoie une fonction qui fournit les entrées restantes lorsqu’elle est appelée plus tard.
Une fonction de salutation partiellement appliquée à « Hello » peut ensuite accepter « Ana » et renvoyer « Hello, Ana ».
Argument
Un argument est une valeur fournie à un appel de fonction, associée selon sa position à un paramètre ou regroupée parmi les entrées restantes.
Dans area(4, 2.5), les arguments sont 4 et 2,5, quels que soient les noms donnés aux paramètres.

C

Cadre de pile
Un cadre de pile contient l’état d’exécution d’un appel de fonction actif, notamment ses paramètres, ses variables locales et son point de reprise.
Deux appels récursifs actifs peuvent chacun conserver une valeur différente de n parce qu’ils possèdent des cadres distincts.
camelCase
Le camelCase est un style de nommage dont le premier mot est en minuscules et les mots suivants commencent par une majuscule, couramment utilisé pour les noms de fonctions JavaScript.
Le nom calculateTotal décrit une action et distingue ses deux mots sans espace ni trait de soulignement.
Cas de base
Un cas de base est le chemin d’arrêt d’une fonction récursive : lorsque le problème a atteint une forme simple, la fonction renvoie une valeur sans s’appeler à nouveau.
Pour une factorielle sur les entiers positifs ou nuls, le test n <= 1 arrête les appels à 0 ou à 1.
Cas récursif
Un cas récursif traite le problème en appelant la même fonction sur une entrée réduite et en utilisant le résultat renvoyé pour terminer l’appel courant.
L’expression n * factorial(n - 1) attend la factorielle plus petite avant de la multiplier par le n de cet appel.
Chaîne de méthodes
Une chaîne de méthodes utilise la valeur renvoyée par une méthode comme objet receveur de la méthode suivante, ce qui permet d’enchaîner plusieurs étapes de traitement d’un tableau.
Un filtre suivi d’une méthode map sélectionne d’abord les entrées, puis transforme uniquement les éléments conservés.
Chaîne de portées
La chaîne de portées est la succession de la portée courante et des portées englobantes parcourues vers l’extérieur pour résoudre un nom, jusqu’à la première déclaration.
Un calcul intérieur lit son amount local avant de considérer une variable de même nom dans une portée extérieure.
Clause de garde
Une clause de garde vérifie une condition particulière et provoque une sortie anticipée, ce qui sépare cette branche exceptionnelle du travail principal de la fonction.
Le test if (b === 0) { return null; } protège la division placée après lui dans safeDivide.
Comparateur
Un comparateur est une fonction de rappel de tri dont la valeur de retour négative, positive ou nulle détermine l’ordre relatif de deux entrées comparées.
Le comparateur (a, b) => a - b trie les nombres par ordre croissant tandis que sort réorganise le tableau d’entrée.
Composition de fonctions
La composition de fonctions combine des fonctions en transmettant la sortie de l’une à l’entrée d’une autre, l’appel intérieur étant effectué avant l’appel extérieur.
Avec f(g(x)), changer l’ordre en g(f(x)) peut modifier le résultat même lorsque les deux fonctions acceptent des nombres.
Corps concis
Un corps concis est un corps de fonction fléchée constitué d’une expression dont la valeur devient le résultat de l’appel sans instruction return explicite.
Le corps constitué d’une expression dans (a, b) => a + b renvoie directement la somme des deux arguments fournis.
Corps de bloc
Un corps de bloc contient des instructions entre accolades et nécessite un return explicite pour qu’une fonction fléchée renvoie une valeur calculée.
La fonction fléchée (n) => { n * 2; } calcule un produit mais renvoie undefined parce qu’elle ne contient pas d’instruction return.
Corps de fonction
Le corps d’une fonction contient les instructions exécutées lors d’un appel ; une fonction ordinaire place ces instructions entre accolades.
Si le corps de printHeading contient trois instructions d’affichage, les trois s’exécutent à nouveau à chaque appel de cette fonction.

D

Déclaration de fonction
Une déclaration de fonction définit une fonction nommée avec le mot-clé function et la rend disponible dès le début de sa portée.
L’appel greet("Li") peut apparaître avant la déclaration écrite de greet dans la même portée.
Déstructuration de tableau
La déstructuration de tableau affecte les éléments d’un tableau à des noms distincts, ce qui permet à un tableau renvoyé de fournir plusieurs résultats nommés.
La déclaration const [low, high] = minMax(values); extrait les deux éléments du tableau renvoyé.

E

Effet de bord
Un effet de bord est une modification extérieure au calcul local d’une fonction, comme un affichage, la modification d’une variable extérieure ou la mutation d’un tableau d’entrée.
Une fonction de rappel qui ajoute un élément à une liste partagée a un effet de bord même si elle renvoie aussi une valeur utile.
Expression de fonction
Une expression de fonction crée une fonction comme valeur au sein d’une expression, par exemple à droite d’une affectation à une variable.
Dans const square = function (n) { return n * n; };, l’expression fournit la valeur stockée dans square.
Expression de fonction immédiatement invoquée
Une expression de fonction immédiatement invoquée, ou IIFE, crée une fonction et l’appelle aussitôt, souvent pour donner une portée privée au code ancien.
Les parenthèses finales dans (function () { var hidden = 1; })(); invoquent la fonction qui vient d’être créée.
Expression de fonction nommée
Une expression de fonction nommée crée une fonction dotée d’un nom interne disponible dans son propre corps, notamment pour les appels récursifs.
Dans const factorial = function fact(n) { /* body */ };, la variable extérieure est factorial et le nom interne est fact.

É

État partagé
Un état partagé est constitué de données conservées auxquelles plusieurs fonctions peuvent accéder et qu’elles peuvent mettre à jour, comme une liaison capturée par des fonctions issues d’un même appel.
Une opération de dépôt et une fonction de lecture du solde renvoyées ensemble peuvent toutes deux accéder au même balance privé.
État privé
Un état privé est constitué de données dans la portée locale d’une fermeture auxquelles le code extérieur ne peut accéder ou qu’il ne peut modifier que par les opérations qui les exposent.
Un limiteur expose une opération d’autorisation ou de refus tout en gardant son compteur interne used inaccessible directement.

F

Fabrique de fonctions
Une fabrique de fonctions crée et renvoie des fonctions configurées, en utilisant l’accès conservé par une fermeture pour retenir les arguments ou l’état local de son appel.
Appeler makeMultiplier(3) renvoie une fonction qui conserve 3 en mémoire tout en acceptant plus tard un nombre à multiplier.
Fermeture
Une fermeture associe une fonction à l’accès conservé à sa portée de création, ce qui permet aux variables capturées de rester utilisables après un retour extérieur.
Une fonction compteur peut continuer à incrémenter son count privé après la fin de la fabrique qui l’a créée.
Fonction
Une fonction est un ensemble réutilisable d’instructions qui effectue une tâche lorsqu’il est appelé, en acceptant éventuellement des entrées et en renvoyant éventuellement un résultat.
Un script appelle printHeading("Report") et printHeading("Totals") pour réutiliser une même fonction de titre.
Fonction anonyme
Une fonction anonyme est une expression de fonction sans nom de fonction explicite, souvent stockée dans une variable ou passée comme argument.
L’expression function (n) { return n * n; } n’a pas de nom de fonction interne dans sa syntaxe écrite.
Fonction d’ordre supérieur
Une fonction d’ordre supérieur accepte une fonction comme argument, renvoie une fonction comme résultat, ou combine ces deux façons de manipuler des valeurs de fonction.
Les méthodes de tableau acceptent des fonctions de rappel, tandis qu’une fabrique de multiplicateurs renvoie une fonction de calcul configurée.
Fonction de rappel
Une fonction de rappel est une fonction passée comme argument pour être invoquée par la fonction qui la reçoit, celle-ci contrôlant ses entrées et l’utilisation de sa valeur de retour.
Une fonction auxiliaire countIf appelle sa fonction de rappel de test pour chaque élément et compte ceux dont le résultat du test est une valeur vraie.
Fonction de rappel de transformation
Une fonction de rappel de transformation renvoie une valeur de remplacement pour un élément d’entrée, ce qui permet à une fonction de transformation de regrouper les sorties dans un nouveau tableau.
La fonction de rappel (n) => n * n transforme les éléments de [1, 2, 3] en leurs carrés lors d’une opération de transformation.
Fonction de rappel différée
Une fonction de rappel différée est planifiée pour s’exécuter plus tard, tandis que le code qui suit l’appel de planification peut continuer sans attendre son exécution.
Passer sayHi à setTimeout permet aux instructions suivantes de s’exécuter avant l’affichage de la salutation planifiée.
Fonction de rappel synchrone
Une fonction de rappel synchrone s’exécute pendant l’exécution de la fonction qui la reçoit et termine son travail avant que celle-ci ne revienne à son propre appelant.
Une fonction de rappel de map traite les éléments du tableau avant que l’appel de map terminé ne fournisse son tableau de résultats.
Fonction en ligne
Une fonction en ligne est une expression de fonction écrite directement là où sa valeur est nécessaire, comme une fonction fléchée dans la liste d’arguments d’un appel.
La fonction fléchée dans repeat(3, (i) => console.log(i)) fournit l’action sans déclaration nommée distincte.
Fonction enveloppante
Une fonction enveloppante est une fonction renvoyée qui ajoute un comportement autour d’un appel de fonction existant, en transmettant souvent ses entrées et en préservant son résultat.
Une fonction enveloppante de journalisation affiche les arguments fournis, appelle la fonction d’origine, puis renvoie son résultat.
Fonction enveloppante à exécution unique
Une fonction enveloppante à exécution unique conserve un indicateur d’achèvement et un premier résultat afin que les appels ultérieurs puissent réutiliser ce résultat sans répéter une opération terminée.
Un indicateur distinct permet à une fonction enveloppante à exécution unique de garder en mémoire que son premier appel s’est terminé, même lorsque le résultat était 0.
Fonction fléchée
Une fonction fléchée est une expression de fonction écrite avec une flèche entre ses paramètres et son corps ; elle n’a pas ses propres liaisons pour this et arguments.
La fonction fléchée (n) => n * 2 fournit une courte fonction de rappel de transformation à une méthode de tableau comme map.
Fonction pure
Une fonction pure calcule sa sortie à partir de ses seuls arguments et n’apporte aucune modification à l’extérieur de l’appel, y compris aucun affichage dans la console.
Une fonction qui ne fait que renvoyer n * 2 est pure ; afficher le produit introduirait un effet de bord.

L

Liaison
Une liaison associe un nom à une valeur stockée dans une portée donnée, ce qui permet aux variables de même nom dans des portées différentes de rester distinctes.
Une affectation met à jour la liaison accessible la plus proche ; une déclaration intérieure crée une liaison locale distincte.
Liaison d’itération
Une liaison d’itération est la liaison distincte de variable de boucle créée pour une itération par let dans un en-tête de boucle for, que les fermetures peuvent conserver.
Des fonctions fléchées stockées issues de différentes itérations avec let i peuvent renvoyer des valeurs différentes après la fin de la boucle.
Littéral d’objet
Un littéral d’objet crée un objet à l’aide d’accolades et de propriétés nommées ; pour le renvoyer directement depuis un corps concis de fonction fléchée, on l’entoure de parenthèses.
La fonction fléchée (n) => ({ value: n }) renvoie un objet au lieu de traiter ses accolades comme un bloc d’instructions.

M

Masquage
Le masquage se produit lorsqu’une déclaration intérieure cache une déclaration extérieure de même nom dans la portée intérieure, donnant au nom une liaison différente.
Un paramètre nommé count masque un count extérieur dans cette fonction sans modifier la liaison extérieure.
Mode strict
Le mode strict est un mode d’exécution JavaScript qui rejette l’affectation à des noms non déclarés, ce qui aide à éviter les variables globales accidentelles.
Commencer un script classique par "use strict"; fait qu’une affectation count = 5; sans déclaration provoque une ReferenceError.
Mutation
Une mutation modifie le contenu d’une valeur existante comme un tableau, rendant cette modification visible par les autres références à ce tableau.
Une fonction qui appelle arr.push(3) modifie le tableau même que le code appelant lui a fourni comme argument.

O

Objet arguments
L’objet arguments est une collection ressemblant à un tableau qui contient les entrées transmises à une fonction ordinaire ; il diffère d’un véritable tableau issu d’un paramètre du reste.
Le code ancien peut lire arguments[0], mais ne peut pas appeler arguments.map comme une méthode ordinaire de tableau.

P

Paramètre
Un paramètre est un nom local dans la définition d’une fonction qui reçoit la valeur d’un argument lorsque la fonction est appelée.
Les noms width et height sont des paramètres dans function area(width, height) { return width * height; }.
Paramètre du reste
Un paramètre du reste regroupe les arguments d’appel restants dans un véritable tableau ; précédé de trois points, il apparaît comme dernier paramètre.
Dans function log(label, ...values) { /* body */ }, le premier argument est distinct du tableau du reste.
Paramètre par défaut
Un paramètre par défaut utilise une expression donnée lorsque son argument vaut undefined, notamment lorsque le code appelant omet cet argument.
Le paramètre level = 50 conserve un 0 explicite, mais fournit 50 lorsque l’argument est manquant.
Pile d’appels
La pile d’appels enregistre les appels de fonctions inachevés, place chaque nouvel appel au sommet et retire son cadre lorsque cet appel se termine.
Pendant que sumOfSquares attend square(3), l’appel de square possède un cadre au-dessus de celui de la fonction appelante en attente.
Portée de bloc
La portée de bloc limite une déclaration let ou const au bloc qui l’entoure et au code qui y est imbriqué, rendant cette déclaration indisponible au code extérieur.
Un let message déclaré dans un corps if ne peut pas être lu par une instruction située après la fin de ce bloc.
Portée de fonction
La portée de fonction rend un paramètre ou une déclaration var local à la fonction qui l’entoure, même lorsque var est écrit dans un bloc intérieur.
Un var result affecté dans un bloc if peut être renvoyé plus tard depuis le corps de la fonction qui l’entoure.
Portée globale
La portée globale contient les déclarations de niveau supérieur d’un script classique et rend ces noms disponibles aux fonctions dont les chaînes de portées y donnent accès.
Un count de niveau supérieur dans un script peut devenir un état partagé lorsque plusieurs fonctions le lisent ou le mettent à jour.
Portée lexicale
La portée lexicale détermine les déclarations extérieures accessibles à partir de l’imbrication écrite du code, et non de l’emplacement d’un appelant ultérieur.
Une fonction de lecture de niveau supérieur lit toujours sa variable extérieure lorsqu’elle est appelée dans une fonction dotée d’une variable locale de même nom.
Prédicat
Un prédicat est une fonction de test dont le résultat détermine si une entrée satisfait à une condition, utilisée par des méthodes comme filter ou find.
Le prédicat (n) => n > 4 sélectionne les nombres qu’un filtre conserve sans modifier lui-même leurs valeurs.

R

Réaffectation
Une réaffectation modifie la valeur stockée dans une variable ou un paramètre existant, sans modifier une autre variable qui contenait l’ancienne valeur.
Dans une fonction, arr = [] redirige le paramètre sans remplacer la référence au tableau du code appelant.
Récursivité
La récursivité se produit lorsqu’une fonction s’appelle elle-même pour résoudre des versions plus petites d’une tâche, avec un cas d’arrêt qui ne nécessite pas de nouvel appel à elle-même.
Une fonction factorielle multiplie son entrée par le résultat de cette même fonction appliquée à une entrée inférieure de un.
Référence de fonction
Une référence de fonction est une valeur qui désigne une fonction et permet à une autre variable ou à un autre élément qui la reçoit d’appeler ultérieurement cette même fonction.
Après const alias = square;, l’appel alias(4) invoque la fonction également accessible par square.
Remontée des déclarations
La remontée des déclarations décrit l’enregistrement des déclarations avant l’exécution de leur portée, avec des règles d’accès initial différentes pour les fonctions, var, let et const.
Lire un var remonté avant son affectation donne undefined ; un appel anticipé à une fonction déclarée peut s’exécuter.
Retour anticipé
Un retour anticipé termine un appel avant l’exécution des instructions suivantes, souvent pour traiter une entrée particulière avant le travail principal de la fonction.
Une fonction auxiliaire de division peut renvoyer null pour un diviseur nul avant que l’exécution atteigne l’instruction de division.

S

Syntaxe de décomposition
La syntaxe de décomposition sépare les éléments d’un tableau en arguments d’appel distincts, à l’aide de trois points placés avant l’expression du tableau dans la liste d’arguments.
L’appel Math.max(...[3, 7, 2]) transmet trois nombres au lieu de transmettre un tableau à Math.max.

T

Trace de pile
Une trace de pile répertorie les appels actifs lorsqu’une erreur s’est produite, en commençant par le plus récent puis en remontant les appels qui y ont conduit.
Des entrées répétées pour une fonction récursive peuvent aider à repérer une condition d’arrêt que l’entrée n’atteint jamais.

V

Valeur de retour
Une valeur de retour est l’unique valeur produite par un appel de fonction et fournie au code appelant pour être stockée ou utilisée dans une autre expression.
Si double(5) renvoie 10, l’expression double(5) + 1 peut immédiatement utiliser cette valeur pour produire 11.
Valeur fausse
Une valeur fausse se comporte comme false dans un test de vérité, ce qui explique pourquoi une ancienne valeur par défaut utilisant le OU logique peut remplacer des entrées valides comme zéro.
L’expression level || 50 remplace 0, tandis qu’un paramètre par défaut conserve cette valeur fournie.
Variable capturée
Une variable capturée est une liaison accessible par une fermeture, de sorte que la fonction peut lire sa valeur actuelle au lieu d’une copie figée au moment de sa création.
Faire passer un greeting extérieur de « Hi » à « Hello » change la valeur renvoyée par un appel ultérieur d’une fonction qui lit greeting.
Variable locale
Une variable locale appartient à une portée limitée, de fonction ou de bloc, ce qui permet de garder ses données de travail distinctes des données extérieures de nom similaire.
Deux fonctions indépendantes peuvent chacune utiliser un total local sans que leurs additions interfèrent.

Z

Zone morte temporaire
La zone morte temporaire est la période qui précède l’initialisation d’une liaison let ou const, pendant laquelle accéder à cette liaison provoque une ReferenceError.
Une lecture anticipée trouve une variable locale qui masque la variable extérieure, même si elle n’est pas encore initialisée, au lieu d’utiliser la valeur extérieure.

À propos de cette unité

Par StudeliSignaler une erreur

Crée ton propre Matériel d'Étude

Transforme tes notes, diapos et documents en Guides d'Étude, Questions Pratiques, Flashcards et 6 autres outils.

Commencer