Лист за преговор: Maîtrise des fondamentaux JavaScript modernes

📋 Plan du Cours

  1. Variables (var, let, const)
  2. Types et coercition
  3. Fonctions (déclaration, fléchées, callbacks)
  4. Scope et closures
  5. Hoisting
  6. Le mot-clé this
  7. Objets et prototypes
  8. Tableaux et méthodes
  9. Destructuring
  10. Spread et Rest
  11. Promesses
  12. Async/Await

📖 1. Variables (var, let, const)

🔑 Notions clés & Définitions

  • Variable : Conteneur pour stocker une valeur. En JavaScript, variables permettent de sauvegarder, manipuler et réutiliser des données.
  • var : Ancienne déclaration de variable, fonction-scopée, susceptible de causer des problèmes de hoisting et de portée.
  • let : Nouvelle déclaration, bloc-scopée, introduite en ES6, évite certains pièges de var.
  • const : Variable dont la valeur ne peut pas être réassignée après initialisation, bloc-scopée, utilisée pour les constantes.
  • Scope (portée) : La zone du code où une variable est accessible. var a une portée fonction, let et const ont une portée bloc.
  • Hoisting : Mécanisme où les déclarations de variables (avec var) sont remontées en haut de leur scope, mais pas leur initialisation.

📝 Points essentiels

  • var est global ou local à la fonction, peut entraîner des erreurs de portée et de hoisting.
  • let et const sont bloqués au niveau du bloc, évitant ainsi certains bugs liés à la portée.
  • const doit être initialisée lors de sa déclaration ; sa valeur ne peut pas être réaffectée, mais si c’est un objet ou tableau, ses propriétés peuvent l’être.
  • La différence principale entre let et const : la mutabilité de la valeur (réassignable ou non).
  • Hoisting : avec var, la déclaration est remontée, mais pas l'initialisation ; avec let/const, la variable est en "zone morte" jusqu’à déclaration effective.

💡 À retenir

Utilise let pour des variables qui changent, const pour des constantes. Évite var sauf nécessité spécifique, pour prévenir les bugs liés à la portée et au hoisting.

Mini quiz

  1. Quelle différence principale entre var et let ?
  2. Peut-on réassigner une variable déclarée avec const ? Pourquoi ?
  3. Que se passe-t-il si on tente d’accéder à une variable déclarée avec let avant sa déclaration ?
  4. Qu’est-ce que le hoisting en JavaScript ?
  5. Pourquoi privilégier const par défaut ?

Comparaisons utiles

VariableScopeRéassignableHoistingUsage recommandé
varFonctionOuiOui (initialisation pas)À éviter sauf legacy
letBlocOuiNon (zone morte)Généralement préféré
constBlocNonNon (zone morte)Pour constantes, objets mutables

Cas pratiques réels

  • Gestion d’un compteur :
let count = 0;
count++; // OK
  • Constante pour une configuration :
const API_KEY = 'abc123';
// API_KEY = 'xyz'; // Erreur, non réassignable
  • Erreur fréquente avec var :
if (true) {
  var x = 5;
}
console.log(x); // 5, car var est fonction-scopée, pas bloc-scopée

Règles importantes à retenir

  • Préférer let et const pour éviter les bugs liés à la portée.
  • Toujours initialiser une const lors de sa déclaration.
  • Comprendre le hoisting pour éviter les erreurs d’accès à des variables non encore déclarées.
  • Utiliser const par défaut, sauf si la variable doit changer.

Astuce de mémorisation

Pense à var comme un ancien outil, souvent source de bugs, alors que let et const sont conçus pour une gestion claire de la portée et de la mutabilité.
const = constante, immuable (sauf objets), let = variable mutable.

Version avancée / mode "crack" :
Maîtrise la portée, le hoisting et la mutabilité pour écrire un code robuste, performant et sans bugs subtils liés à la déclaration des variables. Connais les pièges du moteur JS, notamment comment var peut causer des effets de bord difficiles à diagnostiquer.

📖 2. Types et coercition

🔑 Notions clés & Définitions

  • Type de données : classification des valeurs en JavaScript (Number, String, Boolean, Object, Undefined, Null, Symbol, BigInt).
    Intuitive : ce que la valeur "est".
    Technique : classification selon la représentation interne du moteur JS.

  • Coercition : conversion automatique ou explicite d’un type en un autre lors d’opérations.
    Intuitive : JavaScript "force" une valeur à changer de type pour que l’opération soit possible.
    Technique : conversion implicite (coercition automatique) ou explicite (avec cast).

  • Coercition implicite : conversion automatique lors d’opérations (ex : ==, + avec chaîne).
    Exemple : '5' + 1'51'.
    Piège : peut conduire à des résultats inattendus.

  • Coercition explicite : conversion volontaire via des fonctions (String(), Number(), Boolean()).
    Exemple : Number('123')123.

  • Equality (==) vs Strict equality (===) :

    • == : compare après coercition si nécessaire.
    • === : compare sans coercition, plus sûr.

📝 Points essentiels

  • JavaScript possède des types dynamiques, ce qui permet de changer le type d’une variable à tout moment.

  • La coercition peut entraîner des bugs difficiles à repérer, notamment avec ==.

  • La comparaison stricte (===) est recommandée pour éviter les surprises liées à la coercition.

  • La coercition implicite suit des règles précises :

    • null et undefined ne se convertissent pas en nombre ou chaîne lors de == mais ont des comportements spécifiques.
    • Avec +, si l’un des opérandes est une chaîne, l’autre est converti en chaîne.
    • Avec -, *, /, les opérandes sont convertis en nombres.
  • La conversion en nombre (Number()) :

    • null0
    • true1
    • false0
    • '' (chaîne vide) → 0
    • undefinedNaN

💡 À retenir

La coercition en JavaScript peut être source de bugs subtils. Privilégier === et maîtriser les règles de conversion pour écrire un code fiable et prévisible.

📖 3. Fonctions (déclaration, fléchées, callbacks)

🔑 Notions clés & Définitions

  • Fonction déclarée (Function Declaration)
    Définition simple : Fonction définie avec le mot-clé function et accessible dans tout le scope (hoisting).
    Définition technique : Fonction hoistée, peut être appelée avant sa déclaration dans le code, possède son propre scope local.
    Exemple :

    function add(a, b) {
      return a + b;
    }
    

    Piège fréquent : Ne pas comprendre le hoisting, ce qui peut causer des erreurs si on tente d'appeler une fonction déclarée avant sa définition dans un bloc.

  • Fonction fléchée (Arrow Function)
    Définition simple : Syntaxe compacte pour écrire des fonctions, ne possède pas son propre this.
    Définition technique : Fonction anonyme, non hoistée, lexicalement liée à this (hérite du contexte parent).
    Exemple :

    const multiply = (x, y) => x * y;
    

    Piège fréquent : Perte de this dans les callbacks ou méthodes d’objet, à cause de la liaison lexicale.

  • Callback
    Définition simple : Fonction passée en argument à une autre fonction, exécutée plus tard.
    Définition technique : Fonction de rappel utilisée pour gérer l’asynchronisme ou la logique après une opération.
    Exemple :

    setTimeout(() => {
      console.log('Timeout terminé');
    }, 1000);
    

    Piège fréquent : Mauvaise gestion de l’asynchronisme, oubli de gérer les erreurs dans les callbacks.

  • Scope d’une fonction
    Définition simple : Zone où une fonction peut accéder à ses variables.
    Définition technique : La portée locale ou globale, dépendant de la déclaration (var, let, const).

  • Closures
    Définition simple : Fonction qui "se souvient" du contexte dans lequel elle a été créée.
    Définition technique : Fonction interne qui garde accès aux variables de sa fonction parente même après l'exécution de cette dernière.

📝 Points essentiels

  • La déclaration classique (function) est hoistée, contrairement aux fonctions fléchées (=>) qui ne le sont pas.
  • Les fonctions fléchées ne possèdent pas leur propre this, elles héritent celui du scope lexical.
  • Les callbacks permettent la gestion de l’asynchronisme, mais peuvent compliquer la lecture du code (callback hell).
  • La compréhension du scope et des closures est cruciale pour maîtriser la gestion des variables et des fonctions en JavaScript.
  • La différence entre déclaration et expression de fonction impacte la disponibilité dans le code (hoisting).

💡 À retenir

Les fonctions en JavaScript, qu'elles soient déclarées ou fléchées, ont des comportements distincts liés à leur hoisting et à leur liaison de this. Maîtriser ces différences est essentiel pour écrire du code robuste, notamment en asynchrone et dans la conception d’API modulaires.

📖 4. Scope et closures

🔑 Notions clés & Définitions

  • Scope (portée)
    Définition simple : La zone dans laquelle une variable est accessible.
    Définition technique : La portée détermine la visibilité et la durée de vie d’une variable dans le code, pouvant être global, local (dans une fonction) ou de bloc (avec let/const).
    Exemple :

    let x = 10; // variable dans le scope global
    function test() {
      let y = 5; // variable dans le scope local de la fonction
    }
    
  • Closure (fermeture)
    Définition simple : Fonction qui "se souvient" des variables de son environnement même après que cet environnement a disparu.
    Définition technique : Fonction interne qui conserve une référence à son scope lexical, permettant d’accéder à des variables de ses parents même après leur exécution.
    Exemple :

    function outer() {
      let count = 0;
      return function inner() {
        count++;
        return count;
      }
    }
    const counter = outer();
    console.log(counter()); // 1
    
  • Lexical Scope (portée lexicale)
    Définition : La portée d’une variable est déterminée à l’écriture du code, non lors de l’exécution. La fermeture conserve cette structure.

  • Variable Capture (capture de variable)
    Définition : Lorsqu’une closure "capture" des variables de son scope parent, permettant leur utilisation ultérieure.

  • Hoisting (levée de déclaration)
    Définition : Mécanisme où les déclarations de variables (avec var) et de fonctions sont remontées en haut de leur scope lors de la compilation, influençant leur disponibilité.

📝 Points essentiels

  • Scope global vs local :

    • var a une portée fonction ou globale, ce qui peut causer des erreurs si mal utilisé.
    • let et const ont une portée de bloc, limitant leur visibilité.
  • Closures :

    • Permettent de maintenir un état privé dans des fonctions.
    • Utilisées pour créer des fonctions avec mémoire (ex : compteur, gestion d’état).
  • Problèmes courants :

    • Variables capturées dans une boucle avec var partagent la même référence, causant des bugs.
    • Confusion entre hoisting et initialisation.
  • Règle d’or :

    • Préférer let et const pour éviter les pièges de hoisting et de portée globale.
    • Utiliser les closures pour encapsuler l’état et éviter la pollution du scope global.

💡 À retenir

Les closures permettent de créer des fonctions avec un état privé en conservant leur environnement lexical, tandis que la compréhension du scope évite les erreurs liées à la visibilité et à la durée de vie des variables. Maîtriser ces concepts est essentiel pour écrire du code robuste, performant et sécurisé en JavaScript.

Mini quiz

  1. Quelle différence principale entre var et let en termes de scope ?
  2. Qu’est-ce qu’une closure ? Donnez un exemple simple.
  3. Pourquoi le hoisting peut poser problème avec var ?
  4. Comment éviter la capture incorrecte de variables dans une boucle avec var ?
  5. Que conserve une closure même après la fin de l’exécution de la fonction parente ?

Comparaisons utiles

Conceptvarlet / const
ScopeFonction ou globalBloc (délimité par {})
HoistingOui, déclaration remontéeNon, pas d’effet de hoisting sur l’initialisation
RéaffectationPossiblePossible avec let, non avec const
RedéclarationAutorisée dans le même scopeNon, provoque une erreur

Cas pratiques réels

  • Encapsulation d’état privé : Utiliser des closures pour créer des modules ou des gestionnaires d’état sans polluer le scope global.
  • Gestion d’événements : Capturer des variables dans des callbacks pour maintenir leur valeur lors de l’événement.
  • Boucles et closures : Corriger le problème classique de capture de variable dans une boucle en utilisant une IIFE ou let.

Note importante : La maîtrise du scope et des closures est la clé pour écrire un JavaScript avancé, performant et sécurisé, notamment dans la gestion de l’état, la modularité et la programmation asynchrone.

📖 5. Hoisting

🔑 Notions clés & Définitions

  • Hoisting (remontée)
    Définition simple : Comportement où certaines déclarations (variables, fonctions) sont "levées" en haut de leur contexte d'exécution avant l'exécution du code.
    Définition technique : Mécanisme par lequel le moteur JavaScript déclare et initialise certaines entités (variables, fonctions) lors de la phase de compilation, avant l'exécution du script.

  • Déclarations de variables
    var : La déclaration est levée en haut, mais l'initialisation reste à sa place.
    let et const : La déclaration est levée, mais l'accès avant déclaration provoque une erreur (zone morte).

  • Fonctions
    Function declaration (déclaration de fonction classique) : Entirement hoisted, accessible partout dans le scope.
    Function expression (fonction assignée à une variable) : La variable est levée, mais pas la fonction, ce qui peut causer des erreurs.

  • Zone Morte (Temporal Dead Zone - TDZ)
    Période entre le début du scope et la déclaration où l'accès à let et const provoque une erreur.

  • Scope
    Contexte dans lequel les variables et fonctions sont accessibles. Hoisting dépend du scope (global, fonction, bloc).

📝 Points essentiels

  • Les déclarations avec var sont levées et initialisées à undefined au début du scope.
  • Les déclarations avec let et const sont levées mais restent inaccessibles jusqu'à leur déclaration effective (zone morte).
  • Les fonctions déclarées traditionnellement sont entièrement hoisted, permettant leur appel avant leur définition dans le code.
  • Les expressions de fonction (fonction anonyme assignée à une variable) ne sont pas hoisted, seule la variable l’est, mais elle reste undefined jusqu’à l’affectation.
  • La compréhension du hoisting évite les bugs liés à l’ordre d’écriture du code.

💡 À retenir

Le hoisting peut entraîner des comportements inattendus si mal compris, notamment avec var et les fonctions. La meilleure pratique consiste à déclarer toutes les variables en début de scope et à préférer les déclarations let et const pour éviter la zone morte.

Mini quiz

  1. Que se passe-t-il si vous essayez d’accéder à une variable déclarée avec let avant sa déclaration ?
  2. La déclaration d’une fonction classique est-elle hoisted ?
  3. Quelle différence principale y a-t-il entre var et let concernant le hoisting ?
  4. Que provoque l’accès à une variable déclarée avec var avant son initialisation ?
  5. Peut-on appeler une fonction déclarée avec une expression de fonction avant sa ligne d’affectation ?

Comparaisons utiles

VariableHoistingInitialisationAccès avant déclarationZone MorteUsage recommandé
varOuiOui (undefined)PossibleNonÀ éviter, privilégier let/const
let / constOuiNon (zone morte)Erreur (ReferenceError)OuiPréféré pour la sécurité
Fonction déclaréeOuiOuiPossibleNonUtiliser pour fonctions globales ou locales

Cas pratique

console.log(a); // undefined (var est hoisted, initialisé à undefined)
var a = 10;

foo(); // Fonction hoisted, appel réussi
function foo() {
  console.log('Hello');
}

console.log(b); // ReferenceError : b n’est pas accessible avant déclaration
let b = 20;

Point à retenir :
Le hoisting influence la visibilité et l’état initial des variables et fonctions. Comprendre ses mécanismes permet d’éviter des bugs subtils et d’écrire un code plus robuste.

📖 6. Le mot-clé this

🔑 Notions clés & Définitions

  • this (en JavaScript)
    Définition simple :
    Le mot-clé this fait référence à l'objet qui est en train d'exécuter la fonction ou le contexte dans lequel la fonction est appelée.
    Définition technique :
    this désigne l'objet contextuel lors de l'exécution d'une fonction, dont la valeur dépend du mode d'appel (appel global, méthode d'objet, constructeur, arrow function, etc.).

  • Contexte d'exécution
    Définition simple :
    L'environnement dans lequel une fonction s'exécute, déterminant la valeur de this.
    Définition technique :
    La référence à l'objet dans lequel la fonction est appelée, influencée par la mode d'appel (direct, méthode, constructeur, arrow).

  • Arrow functions et this
    Définition simple :
    Les fonctions fléchées ne possèdent pas leur propre this, elles héritent celui du contexte parent.
    Définition technique :
    La valeur de this dans une arrow function est fixée lexicalement, c’est-à-dire qu’elle ne change pas selon l’appel.

  • Binding explicite (call, apply, bind)
    Définition simple :
    Méthodes pour forcer la valeur de this lors de l’appel d’une fonction.
    Définition technique :
    call et apply invoquent immédiatement la fonction en fixant this, tandis que bind retourne une nouvelle fonction avec this lié.

  • this dans les constructeurs
    Définition simple :
    Lorsqu’on utilise new, this fait référence à l’objet en cours de création.
    Définition technique :
    Dans une fonction constructeur, this est l’instance nouvellement créée.

📝 Points essentiels

  • La valeur de this dépend du mode d’appel :

    • Appel global : this fait référence à l’objet global (window en navigateur, global en Node.js).
    • Méthode d’objet : this désigne l’objet propriétaire.
    • Fonction fléchée : this hérite du contexte lexical (parent).
    • Appel avec call, apply, bind : this est explicitement défini.
    • Constructeur (new) : this est l’objet en cours de création.
  • Les fonctions fléchées sont souvent utilisées pour préserver le contexte de this dans des callbacks ou closures.

  • La compréhension de this est essentielle pour maîtriser la programmation orientée objet, la gestion des événements, et la conception de modules.

  • Piège classique : oublier que this dans une fonction régulière dépend de l’appel, pas de la déclaration.

💡 À retenir

this en JavaScript est dynamique et dépend du contexte d’appel. La maîtrise de ses règles permet d’éviter de nombreux bugs liés à la portée et au binding, notamment dans les callbacks et les méthodes d’objets.

Mini quiz

  1. Que désigne this dans une fonction fléchée ?

    • a) L’objet global
    • b) La valeur de this du contexte parent
    • c) La fonction elle-même
    • d) L’objet appelant directement
  2. Quelle méthode permet de lier explicitement this à une fonction ?

    • a) call
    • b) apply
    • c) bind
    • d) Toutes les réponses ci-dessus
  3. Que se passe-t-il si vous utilisez new avec une fonction ?

    • a) this devient l’objet global
    • b) this fait référence à l’objet en cours de création
    • c) this est undefined
    • d) La fonction ne peut pas être appelée
  4. Quelle est la principale différence entre call et apply ?

    • a) call exécute la fonction, apply ne le fait pas
    • b) call prend une liste d’arguments, apply un tableau d’arguments
    • c) call modifie this, apply ne le fait pas
    • d) Il n’y a aucune différence

Comparaisons utiles

Cas d’utilisationthis dans une fonction régulièrethis dans une arrow functionthis avec call / apply / bind
Appel globalObjet global (window)Hérite du contexte lexicalPeut être explicitement fixé
Méthode d’objetL’objet propriétaireHérite du contexte lexicalPeut être explicitement fixé
Fonction constructeurInstance créée (this = nouvel objet)Hérite du contexte lexicalPeut être fixé avec call / apply / bind

Cas pratique

const obj = {
  name: 'JavaScript',
  greet: function() {
    console.log(this.name);
  }
};

obj.greet(); // Affiche : JavaScript

const standaloneGreet = obj.greet;
standaloneGreet(); // Peut afficher undefined ou objet global

const arrowGreet = () => {
  console.log(this.name);
};
arrowGreet(); // Hérite du contexte lexical, souvent undefined dans ce cas

// Binding explicite
const boundGreet = obj.greet.bind({ name: 'TypeScript' });
boundGreet(); // Affiche : TypeScript

## 📖 7. Objets et prototypes

### 🔑 Notions clés & Définitions

- **Objet JavaScript**  
  *Définition simple :* Une collection de propriétés (clés/valeurs) représentant une entité ou un concept.  
  *Définition technique :* Structure mutable, mutable, pouvant contenir des données et des méthodes, créée via littéral ou constructeur.  
  *Exemple :*  
  ```js
  const personne = {
    nom: 'Dupont',
    age: 30,
    saluer() { return `Bonjour, je suis ${this.nom}`; }
  };
  • Prototype
    Définition simple : Objet dont hérite un autre objet, permettant la réutilisation de propriétés/méthodes.
    Définition technique : Chaîne de prototypes ([[Prototype]]) permettant la délégation de propriété via le mécanisme de prototype chain.
    Exemple :

    function Personne(nom) {
      this.nom = nom;
    }
    Personne.prototype.saluer = function() { return `Salut, ${this.nom}`; };
    
  • Prototypage
    Définition simple : Processus de création et d'héritage via prototypes.
    Définition technique : Mode de construction d'objets basé sur l'héritage par prototypes, permettant la délégation de propriétés/méthodes.

  • Object.create()
    Définition simple : Méthode pour créer un nouvel objet avec un prototype spécifique.
    Exemple :

    const proto = { saluer() { return 'Hello'; } };
    const obj = Object.create(proto);
    
  • Constructeur (Fonction constructeur)
    Définition simple : Fonction utilisée pour créer des objets avec new, initialisant leurs propriétés.
    Exemple :

    function Voiture(marque) {
      this.marque = marque;
    }
    Voiture.prototype.klaxonner = function() { console.log('Pouet'); };
    const v = new Voiture('Toyota');
    

📝 Points essentiels

  • Héritage par prototype : chaque objet a une référence interne ([[Prototype]]) vers un autre objet, permettant la délégation de propriétés/méthodes.
  • Chaîne de prototypes : si une propriété n’est pas trouvée sur l’objet, JS la cherche dans son prototype, puis dans celui de son prototype, etc.
  • Modification du prototype : ajouter des méthodes ou propriétés à un prototype permet de les partager entre toutes les instances.
  • Object.prototype : le prototype racine, toutes les objets en héritent.
  • Différence entre objet et prototype : un objet est une instance, un prototype est un modèle dont hérite l’objet.

💡 À retenir

La maîtrise du système de prototypes est essentielle pour comprendre l’héritage, la performance et le comportement avancé de JavaScript. La chaîne de prototypes permet une délégation flexible et puissante, mais peut aussi causer des pièges si mal comprise ou modifiée de façon incorrecte.

Mini quiz

  1. Quelle est la différence entre un objet et son prototype ?
  2. Comment créer un objet avec un prototype spécifique en JavaScript ?
  3. Que se passe-t-il si une propriété n’est pas trouvée sur un objet mais existe dans son prototype ?
  4. Pourquoi est-il préférable d’ajouter des méthodes au prototype plutôt qu’à l’objet lui-même ?
  5. Que signifie "héritage par prototype" ?

Comparaisons utiles

ConceptDescriptionExemple
Objet simple vs prototypeObjet : instance concrète, Prototype : modèle d’héritageconst obj = {} vs Object.create(proto)
Fonction classique vs classeFonction constructeur vs classe ES6function Person() {} vs class Person {}

Cas pratique réel

  • Création d’un système d’héritage pour des formes géométriques : définir une classe Forme, puis créer des sous-classes Cercle, Rectangle via prototypes pour partager des méthodes comme calculerSurface() tout en permettant la spécialisation.

Point à retenir :
Les objets en JavaScript sont liés à des prototypes, ce qui permet une délégation efficace et une architecture flexible, mais nécessite une compréhension fine de la chaîne de prototypes pour éviter pièges et bugs.

📖 8. Tableaux et méthodes

🔑 Notions clés & Définitions

  • Tableau (Array)
    Définition simple : Collection ordonnée d’éléments accessibles par leur index.
    Définition technique : Objet itérable dont chaque propriété numérique correspond à un élément.
    Exemple : const fruits = ['pomme', 'banane', 'orange'];
    Point important : Indexation à partir de 0.

  • Méthodes d’itération (forEach, map, filter, reduce)
    Définition simple : Fonctions permettant de parcourir ou transformer un tableau.
    Exemple : array.forEach(item => console.log(item));
    Point important : map retourne un nouveau tableau, forEach modifie en place ou exécute une action, filter filtre, reduce accumule.

  • Méthodes de transformation (map, filter, reduce)
    Définition simple : Fonctions pour créer un nouveau tableau à partir de l’ancien selon une règle.
    Exemple : const doubles = [1,2,3].map(x => x*2);

  • Méthodes de recherche (find, findIndex, includes)
    Définition simple : Permettent de rechercher des éléments dans un tableau.
    Exemple : array.find(item => item > 10);

  • Méthodes de manipulation (push, pop, shift, unshift, splice)
    Définition simple : Modifient la taille ou le contenu du tableau.
    Exemple : array.push(4); ajoute à la fin, pop() enlève le dernier.

📝 Points essentiels

  • Mutabilité : Certaines méthodes modifient le tableau original (push, splice), d’autres créent un nouveau tableau (map, filter).
  • Chaînage : Les méthodes comme map, filter, reduce peuvent être chaînées pour des transformations complexes.
  • Performance : forEach et map sont souvent plus lisibles mais for classique peut être plus performant pour de gros volumes.
  • Différence entre map et forEach : map retourne un nouveau tableau, forEach ne retourne rien.

💡 À retenir

Les tableaux en JavaScript sont des outils puissants pour manipuler des collections. La maîtrise des méthodes d’itération et de transformation est essentielle pour écrire un code clair, performant et idiomatique.

Mini quiz

  1. Quelle méthode utiliser pour transformer un tableau en un autre de même taille ?
  2. Quelle différence principale entre map et forEach ?
  3. Quelle méthode permet de rechercher un élément selon une condition ?
  4. Quel est l’effet de splice sur un tableau ?
  5. Comment ajouter un élément à la fin d’un tableau ?

Comparaisons utiles

MéthodeRetourneModifie le tableau originalUtilisation principale
forEachAucunNonExécuter une action sur chaque élément
mapNouveauNonTransformer chaque élément
filterNouveauNonFiltrer selon une condition
reduceValeur uniqueNonAgréger ou accumuler des valeurs
push / popNouvelle longueur / élémentOuiAjouter ou retirer à la fin

Cas pratique

Supposons un tableau d’objets représentant des utilisateurs :

const users = [
  { id: 1, name: 'Alice', age: 25 },
  { id: 2, name: 'Bob', age: 30 },
  { id: 3, name: 'Charlie', age: 22 }
];
  • Extraire tous les noms :
const names = users.map(user => user.name);
  • Filtrer les utilisateurs majeurs :
const adults = users.filter(user => user.age >= 18);
  • Calculer l’âge total :
const totalAge = users.reduce((sum, user) => sum + user.age, 0);

## 📖 9. Destructuring

### 🔑 Notions clés & Définitions

- **Destructuring (déstructuration)**  
  *Définition simple :* Technique permettant d'extraire facilement des valeurs d'objets ou de tableaux pour les assigner à des variables.  
  *Définition technique :* Syntaxe ES6 qui permet de décomposer des structures de données en variables distinctes, simplifiant l'accès et la manipulation des données.  

- **Destructuring de tableau**  
  *Simple :* Extraction d'éléments par position dans un tableau.  
  *Technique :* Utilisation de crochets `[ ]` pour assigner plusieurs variables en une ligne.  

- **Destructuring d'objet**  
  *Simple :* Extraction de propriétés par nom dans un objet.  
  *Technique :* Utilisation d'accolades `{ }` pour assigner des propriétés à des variables.  

- **Valeurs par défaut**  
  *Définition :* Assignation d'une valeur par défaut lors de la destructuration si la valeur extraite est `undefined`.  

- **Renommage des variables**  
  *Définition :* Lors de la destructuration, on peut donner un autre nom à la propriété ou à l'élément extrait.  

### 📝 Points essentiels

- La destructuration permet d'écrire un code plus clair et plus concis pour extraire des données complexes.  
- Elle fonctionne aussi bien avec des tableaux qu'avec des objets, mais la syntaxe diffère.  
- Lors de la destructuration d'objet, l'ordre n'a pas d'importance, contrairement au tableau.  
- On peut combiner destructuration avec des valeurs par défaut et du renaming pour plus de flexibilité.  
- La destructuration peut être utilisée dans des paramètres de fonctions pour simplifier la gestion des arguments.  

### 💡 À retenir

La destructuration est une technique puissante pour accéder rapidement et proprement aux données, en évitant les accès répétitifs ou verbeux. Elle facilite la manipulation des structures complexes et optimise la lisibilité du code.



### Notions complémentaires (pour approfondir)

- **Destructuring dans les paramètres de fonction**  
  Permet de décomposer directement les arguments passés à une fonction.  
  Exemple :  
  ```js
  function greet({ name, age }) {
    console.log(`Bonjour ${name}, tu as ${age} ans`);
  }
  greet({ name: 'Alice', age: 30 });
  • Utilisation avancée : destructuration imbriquée, combinée avec le spread/rest, pour gérer des structures complexes ou variées.

Mini quiz

  1. Quelle syntaxe utilise-t-on pour destructurer un tableau ?

    • [ ] ou { } ?
    • Réponse : [ ]
  2. Comment donner une valeur par défaut lors de la destructuration d'une propriété ?

    • En utilisant = après la propriété.
    • Exemple : const { x = 10 } = obj;
  3. Peut-on renommer une propriété lors de la destructuration d’un objet ?

    • Oui, en utilisant property: newName.
    • Exemple : const { name: userName } = obj;
  4. La destructuration peut-elle être utilisée dans les paramètres d’une fonction ?

    • Oui, pour simplifier la gestion des arguments.
  5. La destructuration d’un tableau est-elle sensible à l’ordre des éléments ?

    • Oui, elle repose sur la position.

Comparaisons utiles

SyntaxeUtilisationParticularités
[a, b] = arrayDestructuration tableauBasée sur l’ordre, peut sauter des éléments avec des virgules vides
{x, y} = objectDestructuration objetBasée sur les noms de propriété, pas l’ordre

Cas pratique

Exemple avancé :
Supposons un objet complexe avec des données imbriquées :

const user = {
  id: 1,
  name: 'Alice',
  address: {
    city: 'Paris',
    zip: 75000
  }
};

// Destructuration imbriquée
const {
  name,
  address: { city, zip = '00000' }
} = user;

console.log(name); // Alice
console.log(city); // Paris
console.log(zip); // 75000

Objectif : Extraire des données imbriquées tout en assignant des valeurs par défaut.

Point à retenir

La destructuration est une syntaxe essentielle pour écrire un code JavaScript moderne, clair et efficace, permettant d’accéder rapidement aux données structurées tout en améliorant la lisibilité et la maintenabilité.

📖 10. Spread et Rest

🔑 Notions clés & Définitions

  • Spread Operator (...)
    • Définition simple : Permet d'étaler ou de copier les éléments d'un tableau ou les propriétés d'un objet dans un nouvel ensemble.
    • Définition technique : Opérateur syntaxique ES6 qui décompose un iterable (tableau, objet) en éléments individuels ou propriétés, facilitant la copie, la concaténation ou la déstructuration.
    • Exemple :
      const arr1 = [1, 2];
      const arr2 = [...arr1, 3]; // [1, 2, 3]
      
  • Rest Parameters (...)
    • Définition simple : Permet de rassembler plusieurs arguments en un seul tableau dans une fonction.
    • Définition technique : Syntaxe ES6 pour capturer un nombre indéfini d'arguments dans une fonction, souvent utilisée pour la déstructuration ou la gestion dynamique d'arguments.
    • Exemple :
      function sum(...numbers) {
        return numbers.reduce((acc, val) => acc + val, 0);
      }
      
  • Différence Spread / Rest
    • Spread : utilisé pour décomposer ou étaler.
    • Rest : utilisé pour rassembler ou capturer.
    • Position : Spread dans les expressions, Rest dans les paramètres ou déstructurations.

📝 Points essentiels

  • Utilisation du Spread :

    • Copier des objets ou tableaux (copie superficielle).
    • Fusionner plusieurs tableaux ou objets.
    • Passer des éléments individuels à une fonction (ex : Math.max(...array)).
  • Utilisation du Rest :

    • Récupérer un nombre variable d'arguments dans une fonction.
    • Déstructurer un tableau ou objet tout en extrayant certains éléments ou propriétés.
  • Pièges fréquents :

    • Copie superficielle : pour objets imbriqués, spread ne clone pas en profondeur.
    • Position du ... : doit être en dernier dans la liste des paramètres (rest).
    • Confusion entre spread et destructuration : leur syntaxe est identique mais leur usage diffère.
  • Règles importantes :

    • ... doit être en dernière position dans la liste des paramètres rest.
    • Spread peut s'appliquer à tout iterable (tableau, chaîne, objet avec Object.assign).
  • Mini quiz :

    1. Que fait const newArr = [...oldArr] ?
    2. Quelle est la différence entre ... dans une déclaration de fonction et dans une expression ?
    3. Peut-on utiliser ... pour cloner un objet imbriqué ? Pourquoi ?
    4. Comment fusionner deux objets avec spread ?
    5. Que se passe-t-il si on met ... avant un paramètre dans une fonction ?
  • Comparaisons utiles :

    • Object.assign() vs spread : ... est plus lisible et évite la mutation.
    • Rest vs paramètres classiques : ... dans la déclaration de fonction pour capturer l'ensemble des arguments.
  • Cas pratique :

    • Création d'une fonction qui accepte un nombre variable d'arguments et calcule la moyenne.
    • Fusionner plusieurs objets pour créer une configuration d'application.
    • Cloner un tableau ou un objet pour éviter la mutation.

Point à retenir

L'opérateur ... en JavaScript, selon le contexte, permet soit d'étaler (spread) les éléments d'un iterable ou d'un objet, soit de rassembler (rest) plusieurs arguments ou éléments en un seul tableau ou objet, ce qui est essentiel pour écrire un code flexible, efficace et moderne.

📖 11. Promesses

🔑 Notions clés & Définitions

  • Promesse (Promise)
    Définition simple : Objet représentant une opération asynchrone qui peut réussir ou échouer.
    Définition technique : Objet de l'API JavaScript permettant de gérer la résultat d'une opération asynchrone, avec états (en attente, résolue, rejetée).
    Exemple : new Promise((resolve, reject) => { /* code */ })

  • States (États)
    Définition simple : Les différentes phases d'une promesse : en attente, résolue, rejetée.
    Détails techniques :

    • Pending (en attente) : initial, ni résolue ni rejetée
    • Fulfilled (résolue) : opération réussie, résultat disponible
    • Rejected (rejetée) : erreur survenue, raison disponible
  • Méthodes .then(), .catch(), .finally()
    Définition simple : Fonctions pour gérer la résolution ou l’échec d’une promesse.
    Détails techniques :

    • .then() : pour traiter la valeur résolue
    • .catch() : pour gérer l’erreur rejetée
    • .finally() : s’exécute dans tous les cas, après résolution ou rejet
  • Chaînage de Promesses
    Définition simple : Enchaîner plusieurs .then() pour gérer des opérations successives.
    Détails techniques : Permet de gérer des opérations asynchrones dépendantes, avec propagation des valeurs ou erreurs.

  • Async/Await
    Définition simple : Syntaxe plus lisible pour écrire du code asynchrone, basée sur les promesses.
    Détails techniques :

    • async : pour déclarer une fonction asynchrone
    • await : pour attendre la résolution d’une promesse

📝 Points essentiels

  • Une promesse doit être créée avec new Promise() ou obtenue via une API asynchrone (fetch, setTimeout, etc.).
  • La résolution (resolve) ou le rejet (reject) déclenche l’exécution des .then() ou .catch().
  • La gestion d’erreur doit passer par .catch() pour éviter que des erreurs non traitées ne cassent le flux.
  • La méthode .finally() permet d’exécuter du code après la résolution ou le rejet, peu importe le résultat.
  • La syntaxe async/await simplifie la lecture et l’écriture du code asynchrone, mais repose toujours sur des promesses.
  • Les promesses sont essentielles pour éviter le "callback hell" et gérer proprement la concurrence.

💡 À retenir

Les promesses offrent un contrôle précis et lisible sur l’asynchronie en JavaScript, en permettant de chaîner et de gérer efficacement les opérations complexes, tout en évitant les pièges classiques liés aux callbacks.

Mini quiz

  1. Quelle méthode d’une promesse est utilisée pour gérer une erreur ?
    • Réponse : .catch()
  2. Que retourne la méthode .then() ?
    • Réponse : Une nouvelle promesse, permettant de chaîner.
  3. Quelle syntaxe permet d’écrire du code asynchrone de façon plus lisible ?
    • Réponse : async/await
  4. Que signifie l’état pending d’une promesse ?
    • Réponse : En attente, ni résolue ni rejetée.
  5. Que se passe-t-il si une promesse est rejetée mais qu’il n’y a pas de .catch() ?
    • Réponse : Erreur non traitée, peut causer un crash ou un warning.

Comparaisons utiles

FonctionnalitéPromesseCallbackAsync/Await
SyntaxeChainée, claireNested, difficile à maintenirSyntactiquement simple, linéaire
Gestion erreur.catch()Vérification dans chaque callbacktry/catch autour de await
ConcurrenceFacile à chaînerComplexe à gérerSimplifié avec Promise.all()

Cas pratique réel

function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const success = Math.random() > 0.3;
      success ? resolve('Données récupérées') : reject('Erreur réseau');
    }, 1000);
  });
}

fetchData()
  .then(data => console.log(data))
  .catch(error => console.error(error))
  .finally(() => console.log('Fin du traitement'));

Ce code simule une requête asynchrone avec gestion d’erreur et nettoyage final.

📖 12. Async/Await

🔑 Notions clés & Définitions

  • Async (asynchrone)

    • Définition simple : Fonction qui retourne une promesse et permet d'écrire du code asynchrone de façon plus lisible.
    • Définition technique : Fonction déclarée avec le mot-clé async qui retourne implicitement une promesse, facilitant la gestion des opérations asynchrones.
    • Exemple :
      async function fetchData() {
        return "Données";
      }
      fetchData().then(console.log); // Affiche "Données"
      
  • Await (attendre)

    • Définition simple : Permet de suspendre l'exécution d'une fonction asynchrone jusqu'à ce qu'une promesse soit résolue ou rejetée.
    • Définition technique : Opérateur utilisé à l'intérieur d'une fonction async pour attendre la résolution d'une promesse, rendant le code plus linéaire.
    • Exemple :
      async function getData() {
        const data = await fetch('url');
        console.log(data);
      }
      
  • Promise (Promesse)

    • Définition simple : Objets représentant une opération asynchrone dont on connaît le résultat futur.
    • Définition technique : Objet avec états (pending, fulfilled, rejected) permettant de gérer la résultat ou l'erreur d'une opération asynchrone.
    • Exemple :
      const promise = new Promise((resolve, reject) => {
        setTimeout(() => resolve('OK'), 1000);
      });
      
  • Gestion d’erreurs avec try/catch

    • Définition simple : Mécanisme pour capturer et gérer les erreurs lors de l’utilisation d’await.
    • Exemple :
      async function fetchData() {
        try {
          const response = await fetch('url');
        } catch (error) {
          console.error('Erreur:', error);
        }
      }
      
  • Concurrence & parallélisme

    • Définition simple : Exécuter plusieurs opérations asynchrones en même temps pour optimiser le temps total.
    • Exemple :
      const p1 = fetch(url1);
      const p2 = fetch(url2);
      const results = await Promise.all([p1, p2]);
      

📝 Points essentiels

  • async transforme une fonction en une fonction qui retourne une promesse, simplifiant la gestion des opérations asynchrones.
  • await ne peut être utilisé qu’à l’intérieur d’une fonction async.
  • Utiliser try/catch pour gérer proprement les erreurs dans une fonction async.
  • Promise.all() permet d’exécuter plusieurs promesses en parallèle et d’attendre leur complétion.
  • La syntaxe async/await évite le "callback hell" et rend le code plus lisible, mais ne remplace pas la gestion fine des erreurs ou la parallélisation.
  • Attention : await bloque l’exécution de la fonction, mais pas le thread principal, permettant à l’interface utilisateur de rester réactive.

💡 À retenir

Async/await est une syntaxe moderne qui simplifie la gestion des opérations asynchrones en JavaScript, en rendant le code plus lisible et plus facile à maintenir, tout en permettant une gestion efficace des erreurs et de la concurrence.

📊 Tableaux de Synthèse

Aspectvarlet / const
ScopeFonction ou globalBloc (délimité par {})
HoistingOui, déclaration remontéeNon, zone morte jusqu’à déclaration
RéassignableOuiconst non, let oui
Mutabilité (objets)Réassignable, mutableconst : référence immuable, propriétés modifiables
Usage recommandéÀ éviter sauf legacyPréféré pour clarté et sécurité
Type de donnéesExempleCaractéristiques
Number42, 3.14Numérique
String'Bonjour'Chaîne de caractères
Booleantrue, falseVrai ou faux
UndefinedundefinedVariable déclarée mais non initialisée
NullnullValeur nulle explicitement assignée
Object{ nom: 'Alice' }Collection de paires clé/valeur
SymbolSymbol('id')Identifiant unique
BigInt9007199254740991nNombres très grands

⚠️ Pièges & Confusions Fréquentes

  1. Confondre var et let : var est hoistée, let non, ce qui peut causer des erreurs d’accès.
  2. Utiliser == au lieu de === : risque de coercition implicite inattendue.
  3. Tenter de réassigner une const : erreur, sauf si c’est un objet dont les propriétés peuvent changer.
  4. Accéder à une variable déclarée avec let ou const avant déclaration : erreur de "zone morte".
  5. Oublier que this dans une fonction fléchée hérite du contexte parent, pas de son propre.
  6. Mauvaise gestion des callbacks : oublier de gérer l’asynchronisme ou erreurs.
  7. Se méfier de la coercition lors de comparaisons avec == : résultats surprenants (null == undefined true).

✅ Checklist Examen

  • Vérifie que tu maîtrises la différence entre var, let et const en termes de scope, hoisting et mutabilité.
  • Saisis la différence entre coercition implicite et explicite, et privilégie ===.
  • Connais la syntaxe et le comportement des fonctions déclarées, fléchées et des callbacks.
  • Comprends le concept de scope, de closures et leur impact sur la gestion des variables.
  • Maîtrise le mécanisme de hoisting et ses implications.
  • Explique le rôle et le comportement du mot-clé this dans différentes situations.
  • Savoir manipuler objets, leurs prototypes et méthodes associées.
  • Utilise correctement destructuring, spread et rest pour simplifier le code.
  • Maîtrise la gestion asynchrone avec Promesses, async/await.
  • Vérifie la compréhension des types, de la coercition et des conversions.
  • S’assurer de connaître les pièges liés à la portée, hoisting, et coercition.
  • S’assurer de pouvoir identifier et corriger les erreurs fréquentes liées aux variables et types.

Тествайте знанията си

Тествайте знанията си по Maîtrise des fondamentaux JavaScript modernes с 8 въпроса с множество отговори с подробни корекции.

1. Qu'est-ce qu'une variable déclarée avec var, let ou const en JavaScript ?

2. Quelle différence principale existe-t-il entre `var` et `let` en JavaScript moderne ?

Вземете теста →

Прегледайте с флашкарти

Запомнете ключовите концепции на Maîtrise des fondamentaux JavaScript modernes с 10 интерактивни флашкарти.

Fonction fléchée — particularité `this` ?

Hérite du contexte lexical, pas de son propre `this`.

Variable — définition?

Conteneur pour stocker une valeur.

Coercition implicite — exemple ?

'5' + 1 donne '51'.

Вижте флашкартите →

Similar courses

Създайте свои собствени листове за преговор

Импортирайте курса си и AI генерира листове, тестове и флашкарти за 30 секунди.

Генератор на листове