Fonctions JavaScript, portée et fermetures
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
- 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-laDé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 fonctionTraite 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éesUtilise 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.
- Déclare une fonction et appelle-la
- 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ètresExplique 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’argumentsDonne 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 fonctionRenvoie 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’appelsSuis 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.
- Fais correspondre les arguments aux paramètres
- 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 globaleExplique la portée d’une variable déclarée avec
let,constouvar, 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érenceSuis 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.
- Distingue la portée de bloc, la portée de fonction et la portée globale
- 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émoireDé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.
- Explique ce qu’une fermeture conserve en mémoire
- 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 fonctionTransmets 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érieurReconnais 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.
- Passe une fonction de rappel à une fonction
Fonctions JavaScript : cours
1Dé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 :
| Forme | Avant 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
squarecopie une référence de fonction ; affectersquare(3)stocke son résultat. - Une expression de fonction stockée dans
constne peut être appelée qu’après son initialisation. - Une variable de fonction déclarée avec
varcontientundefinedavant 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
| Corps | Exemple | Résultat de l’appel avec 2 et 3 |
|---|---|---|
| Expression concise | (a, b) => a + b | 5 |
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
returnexplicite 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
thisni leur propreargumentset ne peuvent pas servir de constructeurs.
2Passe 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ôle | Exemple |
|---|---|---|
| Liste de paramètres de la définition | Regrouper les arguments restants | function sum(...numbers) { ... } |
| Liste d’arguments de l’appel | Décomposer les éléments du tableau | sum(...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 à
undefinedexplicite, tout en préservant 0 etnull. - 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
argumentsressemble à 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
returnfournit 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 :
factorial(4)attendfactorial(3).- Cet appel attend
factorial(2). - Cet appel attend
factorial(1). - Le cas de base renvoie 1.
- 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.
3Explique 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éclaration | Limite de portée |
|---|---|
let ou const dans un bloc | Ce bloc |
var dans une fonction | La 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 classique | La portée globale du script |
| Déclaration au niveau supérieur dans un module | Ce 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
letetconstrespectent les limites du bloc ;varrespecte 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éclaration | Avant sa ligne d’initialisation |
|---|---|
| Déclaration de fonction | Sa fonction est disponible |
var | Sa valeur est undefined |
let ou const | L’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.
varvaut initialementundefined;letetconstsont inaccessibles dans leur zone morte temporaire.- Une affectation met à jour une liaison existante ; une déclaration en crée une.
constempê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.
4Utilise 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
varpartagent une liaison ; les itérations d’une boucle avecletreç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.
5Passe 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éthode | Rôle de la fonction de rappel | Résultat de la méthode |
|---|---|---|
map | Renvoyer chaque valeur transformée | Un nouveau tableau de même longueur |
filter | Renvoyer une valeur vraie pour les éléments à conserver | Un nouveau tableau d’éléments sélectionnés |
find | Tester si un élément correspond | Première correspondance, ou undefined |
forEach | Effectuer une action pour chaque élément | undefined |
reduce | Renvoyer l’accumulateur suivant | L’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,filteretfindutilisent les résultats des fonctions de rappel de différentes manières.forEachrenvoieundefined;reducerenvoie 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)appliquegavantf.- L’application partielle fixe certains arguments avant des appels ultérieurs.
Fonctions JavaScript : exemples
1Crée, stocke et appelle une fonction
11 étapes
- 1IntroductionDistingue 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.
- 2ExempleDé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.
nameest 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. - 3ExempleExé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
greetseule est la valeur de la fonction. Les parenthèses dansgreet("Li")demandent son exécution. Même une fonction sans entrée a besoin de parenthèses d’appel, comme danssayHi(). - 4Dé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 uniquementshow;lirait la fonction sans rien afficher. - 5ExplicationConserve la fonction comme valeur
const square = function (n) { return n * n; }; const alias = square;L’expression crée une fonction et
squarela stocke. La deuxième affectation copie sa référence dansalias; elle ne calcule pas de carré.square(3)etalias(3)renvoient tous deux 9.En comparaison,
const answer = square(3);appelle la fonction et stocke le nombre renvoyé. - 6Dé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
squareavant son initialisation avecconstprovoque uneReferenceError. 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. - 7ExempleUtilise 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 etadd(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 variablesconstdoivent donc toujours être initialisées avant leur utilisation. - 8DéfiCorrige un résultat manquant
Pourquoi
add(2, 3)renvoie-t-ilundefined, 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. - 9ConseilRenvoie 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
thisni leur proprearguments, 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. - 10Dé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
copycontient la même fonction appelable queadjust. L’affectation n’a pas appelé la fonction ni stocké de résultat numérique. Remplacerconst copy = adjust;parconst copy = adjust(5);stockerait 7, qui n’est pas appelable. - 11Ré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.
2Suis les entrées, les sorties et les appels en attente
16 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionSuis ce qui entre dans un appel et ce qui en sort
- 2ExempleFais correspondre les arguments selon leur position
- 3ExempleDistingue la mutation de la réaffectation
- 4DéfiConserve l’entrée d’origine
- 5ExplicationLa valeur par défaut s’applique à undefined
- 6ExempleRegroupe, puis décompose
- 7DéfiUtilise une valeur par défaut avec le reste
- 8ExempleRenvoie le nombre dont le code appelant a besoin
- 9ExempleArrête une branche avec un retour anticipé
- 10DéfiÉvalue de l’intérieur vers l’extérieur
- 11ExempleGarde en mémoire l’appelant inachevé
- 12ExplicationDonne à la récursivité un chemin d’arrêt
- 13ExempleRemonte les produits en attente
- 14DéfiCorrige une borne de récursivité
- 15LienLis un échec à travers la pile
- 16RécapitulatifSuis une valeur à chaque étape
3Trouve la déclaration associée à un nom
10 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionDemande-toi où le nom appartient
- 2ExempleCompare les limites de bloc et de fonction
- 3ExempleUtilise l’emplacement de la définition
- 4DéfiSuis une valeur locale et une valeur extérieure
- 5ExplicationArrête-toi à la déclaration la plus proche
- 6Point cléEnregistré ne signifie pas initialisé
- 7DéfiPrévois la lecture d’un nom masqué
- 8ConseilDistingue la réaffectation de la mutation
- 9DéfiCombine une fonction de rappel et le moment de la recherche
- 10RécapitulatifSuis l’emplacement avant la valeur
4Donne aux fonctions renvoyées leur propre mémoire
11 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionConserve l’accès après un retour
- 2ExempleCrée un compteur sans l’appeler
- 3ExempleMets à jour la variable conservée
- 4DéfiCompare des compteurs indépendants
- 5Point cléConserve la liaison, et non un instantané
- 6ExempleCrée un calcul configuré
- 7ExempleConserve un compteur d’utilisations privé
- 8DéfiExplique trois résultats égaux
- 9LienReconnais une portée privée dans le code ancien
- 10DéfiPartage une opération configurée
- 11RécapitulatifSuis le nombre d’environnements existants
5Transmets un comportement et construis des fonctions adaptées
15 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionLaisse une fonction fournir le comportement qui change
- 2ExempleAppelle l’action fournie
- 3DéfiUtilise le résultat d’une fonction de rappel
- 4ConseilExamine tous les arguments de la fonction de rappel
- 5ExempleÉcris un schéma de transformation
- 6ExplicationChoisis la forme du résultat
- 7DéfiSuis une sélection et une transformation
- 8Point cléChoisis explicitement l’ordre numérique
- 9ExempleEnveloppe et transmets un appel
- 10ExplicationGarde en mémoire si un appel a été exécuté
- 11ExempleCompose de l’intérieur vers l’extérieur
- 12ExempleFixe des entrées avant l’appel ultérieur
- 13DéfiPasse une fonction de rappel configurée
- 14DéfiCorrige un résultat perdu par une fonction enveloppante
- 15RécapitulatifVérifie les deux étapes du code d’ordre supérieur
Fonctions JavaScript : QCM
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"); }
Afficher la réponseMasquer la réponse
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
value est égale à son entrée n ?Afficher la réponseMasquer la réponse
{ 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);
Afficher la réponseMasquer la réponse
[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";
}
Afficher la réponseMasquer la réponse
Question 5 sur 10
Que renvoie totalDown(3) ?
function totalDown(n) {
if (n === 0) { return 0; }
return n + totalDown(n - 1);
}
Afficher la réponseMasquer la réponse
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";
}
Afficher la réponseMasquer la réponse
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();
Afficher la réponseMasquer la réponse
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());
Afficher la réponseMasquer la réponse
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());
Afficher la réponseMasquer la réponse
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));
Afficher la réponseMasquer la réponse
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());
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);
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);
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;
}
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;
}
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);
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();
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);
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];
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);
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
function showLabel() { console.log("Ready"); }, quelle instruction appelle la fonction ?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;
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; };
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;
}
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; }
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);
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;
}
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();
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");
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);
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
function printLine() { console.log("---"); }, puis exécute printline();. Que se passe-t-il ?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);
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);
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);
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();
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
}
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();
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);
}
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));
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);
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
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; }
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));
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;
}
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();
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()];
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);
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;
});
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);
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);
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
A
Accumulateur
[5, 10, 15].Appel de fonction
sayHi() exécute son corps, tandis qu’une ligne contenant uniquement sayHi lit la valeur de la fonction.Application partielle
Argument
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
n parce qu’ils possèdent des cadres distincts.camelCase
calculateTotal décrit une action et distingue ses deux mots sans espace ni trait de soulignement.Cas de base
n <= 1 arrête les appels à 0 ou à 1.Cas récursif
n * factorial(n - 1) attend la factorielle plus petite avant de la multiplier par le n de cet appel.Chaîne de méthodes
Chaîne de portées
amount local avant de considérer une variable de même nom dans une portée extérieure.Clause de garde
if (b === 0) { return null; } protège la division placée après lui dans safeDivide.Comparateur
(a, b) => a - b trie les nombres par ordre croissant tandis que sort réorganise le tableau d’entrée.Composition de fonctions
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
(a, b) => a + b renvoie directement la somme des deux arguments fournis.Corps de bloc
(n) => { n * 2; } calcule un produit mais renvoie undefined parce qu’elle ne contient pas d’instruction return.Corps de fonction
printHeading contient trois instructions d’affichage, les trois s’exécutent à nouveau à chaque appel de cette fonction.D
Déclaration de fonction
greet("Li") peut apparaître avant la déclaration écrite de greet dans la même portée.Déstructuration de tableau
const [low, high] = minMax(values); extrait les deux éléments du tableau renvoyé.E
Effet de bord
Expression de fonction
const square = function (n) { return n * n; };, l’expression fournit la valeur stockée dans square.Expression de fonction immédiatement invoquée
(function () { var hidden = 1; })(); invoquent la fonction qui vient d’être créée.Expression de fonction nommée
const factorial = function fact(n) { /* body */ };, la variable extérieure est factorial et le nom interne est fact.É
État partagé
balance privé.État privé
used inaccessible directement.F
Fabrique de fonctions
makeMultiplier(3) renvoie une fonction qui conserve 3 en mémoire tout en acceptant plus tard un nombre à multiplier.Fermeture
count privé après la fin de la fabrique qui l’a créée.Fonction
printHeading("Report") et printHeading("Totals") pour réutiliser une même fonction de titre.Fonction anonyme
function (n) { return n * n; } n’a pas de nom de fonction interne dans sa syntaxe écrite.Fonction d’ordre supérieur
Fonction de rappel
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
(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
sayHi à setTimeout permet aux instructions suivantes de s’exécuter avant l’affichage de la salutation planifiée.Fonction de rappel synchrone
Fonction en ligne
repeat(3, (i) => console.log(i)) fournit l’action sans déclaration nommée distincte.Fonction enveloppante
Fonction enveloppante à exécution unique
Fonction fléchée
(n) => n * 2 fournit une courte fonction de rappel de transformation à une méthode de tableau comme map.Fonction pure
n * 2 est pure ; afficher le produit introduirait un effet de bord.L
Liaison
Liaison d’itération
let i peuvent renvoyer des valeurs différentes après la fin de la boucle.Littéral d’objet
(n) => ({ value: n }) renvoie un objet au lieu de traiter ses accolades comme un bloc d’instructions.M
Masquage
count masque un count extérieur dans cette fonction sans modifier la liaison extérieure.Mode strict
"use strict"; fait qu’une affectation count = 5; sans déclaration provoque une ReferenceError.Mutation
arr.push(3) modifie le tableau même que le code appelant lui a fourni comme argument.O
Objet arguments
arguments[0], mais ne peut pas appeler arguments.map comme une méthode ordinaire de tableau.P
Paramètre
width et height sont des paramètres dans function area(width, height) { return width * height; }.Paramètre du reste
function log(label, ...values) { /* body */ }, le premier argument est distinct du tableau du reste.Paramètre par défaut
level = 50 conserve un 0 explicite, mais fournit 50 lorsque l’argument est manquant.Pile d’appels
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
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
var result affecté dans un bloc if peut être renvoyé plus tard depuis le corps de la fonction qui l’entoure.Portée globale
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
Prédicat
(n) => n > 4 sélectionne les nombres qu’un filtre conserve sans modifier lui-même leurs valeurs.R
Réaffectation
arr = [] redirige le paramètre sans remplacer la référence au tableau du code appelant.Récursivité
Référence de fonction
const alias = square;, l’appel alias(4) invoque la fonction également accessible par square.Remontée des déclarations
var remonté avant son affectation donne undefined ; un appel anticipé à une fonction déclarée peut s’exécuter.Retour anticipé
null pour un diviseur nul avant que l’exécution atteigne l’instruction de division.S
Syntaxe de décomposition
Math.max(...[3, 7, 2]) transmet trois nombres au lieu de transmettre un tableau à Math.max.T
Trace de pile
V
Valeur de retour
double(5) renvoie 10, l’expression double(5) + 1 peut immédiatement utiliser cette valeur pour produire 11.Valeur fausse
level || 50 remplace 0, tandis qu’un paramètre par défaut conserve cette valeur fournie.Variable capturée
greeting extérieur de « Hi » à « Hello » change la valeur renvoyée par un appel ultérieur d’une fonction qui lit greeting.Variable locale
total local sans que leurs additions interfèrent.Z
Zone morte temporaire
À propos de cette unité
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.