Fondations — Objets, portée et destructuration
Créer et inspecter des objets, maîtriser var/let/const, fermetures et destructuration avancée.
Ce bloc consolide ce que vous avez déjà vu en Tw2 (objets, tableaux, fonctions) et l'approfondit : création d'objets sous toutes ses formes, portée des variables (hoisting, Temporal Dead Zone), fermetures et destructuration poussée.
🏗️ Créer un objet
Un objet JavaScript est une collection de paires clé-valeur. C'est la structure de donnée centrale du langage — configurations, réponses d'API, état d'une application, tout finit par transiter sous forme d'objet.
Notation littérale
const personne = {
nom: "Alice",
age: 25,
parler() {
console.log(`Bonjour, je m'appelle ${this.nom}`);
},
};La notation littérale est de loin la plus courante. Les méthodes peuvent utiliser
la syntaxe concise parler() { ... } (équivalent à parler: function() { ... }).
Object.create — créer sans constructeur
const prototypeVide = Object.create(null); // aucun prototype → pas de clés héritées
prototypeVide.nom = "Bob";Object.create(null) produit un objet sans __proto__ — utile pour les dictionnaires
pur (pas d'héritage de toString, hasOwnProperty…).
Constructeur avec new
function Personne(nom, age) {
this.nom = nom;
this.age = age;
}
const alice = new Personne("Alice", 25);
alice instanceof Personne; // trueUn constructeur est une fonction appelée avec new. Sans new, this vaut
le scope global (ou undefined en mode strict) — piège classique.
Sans new, this est le global
Personne("Alice", 25) (sans new) dans un script non-strict assigne
this.nom sur window (ou l'émet une erreur en mode strict). La règle :
toute fonction destinée à être un constructeur commence par une majuscule, et
on l'appelle toujours avec new.
Comparer les façons de créer
Notation littérale
Création directe : `{ key: value }`. Plus simple, recommandée par défaut.
Object.create
Création avec contrôle du prototype (ou prototype null). Utile pour les dictionnaires purs.
Constructeur / class
Réutilisable via `new`. La syntaxe `class` est sucre syntaxique sur le même mécanisme prototype.
🔒 var / let / const — portée et hoisting
JavaScript a trois mots-clés pour déclarer des variables, et ils ne se comportent pas de la même manière.
var | let | const | |
|---|---|---|---|
| Portée | fonction | bloc { ... } | bloc { ... } |
| Hoisting | oui (undefined) | oui (TDZ) | oui (TDZ) |
| Réassignable | ✅ | ✅ | ❌ |
| Redéclarable | ✅ | ❌ | ❌ |
Hoisting et Temporal Dead Zone
console.log(x); // undefined — pas d'erreur, mais valeur "vide"
var x = 10;
console.log(y); // ReferenceError — Temporal Dead Zone
let y = 20;Avec var, la déclaration est "hissée" (hoisted) au début de la fonction/scope,
initialisée à undefined. Avec let/const, la déclaration est également hissée
mais la variable reste dans la Temporal Dead Zone (TDZ) jusqu'à la ligne de
déclaration effective — tout accès avant lève une ReferenceError.
Ce comportement explique pourquoi la pratique moderne recommande :
constpar défaut — le littéral ne sera jamais réassignéletquand la réassignation est nécessaire (boucle, compteur)- Jamais
var— sa portée fonctionnelle et son hoisting sans TDZ sont des sources d'erreur
// Règle pratique — Boucle avec var vs let
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// Affiche : 3, 3, 3 (i est la même variable partagée)
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// Affiche : 0, 1, 2 (chaque itération a sa propre i)Boucle var vs let
Avec var, la variable i est partagée par toutes les itérations. Les
closures capturent la même référence, d'où le 3, 3, 3 final. let crée une
nouvelle liaison par itération, ce qui donne 0, 1, 2. C'est l'origine de
nombreux bugs asynchrones dans le code legacy.
🔐 Fermetures (closures)
Une fermeture est une fonction qui "capture" les variables de son scope englobant, même après que ce scope a fini de s'exécuter.
function creerCompteur() {
let compteur = 0;
return function () {
compteur++;
return compteur;
};
}
const compteur = creerCompteur();
compteur(); // 1
compteur(); // 2
compteur(); // 3Chaque appel à creerCompteur() crée une nouvelle fermeture avec son propre
compteur. La fonction retournée garde une référence vivante à la variable locale
même après le retour de creerCompteur().
Cas d'usage courants
- Fabrique de fonctions paramétrées :
function multiplier(factor) { return x => x * factor } - Data privacy légère : les variables locales ne sont accessibles que par les méthodes retournées
- Callbacks avec contexte :
element.addEventListener("click", () => handler(id))captureid
Closure ≠ performance problème
Les fermetures sont légères et utilisées partout (React, event listeners,
callbacks async). Le piège n'est pas la closure elle-même, mais de capturer
une variable qui change ensuite (ex. var i dans une boucle). Utiliser let
ou créer une IIFE (Immediately Invoked Function Expression) résout ce cas.
📦 Destructuration avancée
La destructuration extrait des valeurs depuis un objet ou un tableau en une seule instruction. Elle s'applique à tous les niveaux et se combine avec des valores par défaut, du renommage et du "rest".
Depuis un objet
const user = { nom: "Alice", age: 25, ville: "Paris" };
// Extraction basique
const { nom, age } = user;
// Renommage
const { nom: prenom } = user;
// Valeur par défaut (si la clé manque)
const { email = "inconnu@email.com" } = user;
// Combiner renommage + défaut
const { nom: nomAffiche, email: courriel = "aucun" } = user;
// Rest — récupérer le "reste" dans un nouvel objet
const { nom, ...autresInformations } = user;
// nom = "Alice", autresInformations = { age: 25, ville: "Paris" }Depuis un tableau
const couleurs = ["rouge", "vert", "bleu"];
const [premier, second] = couleurs;
const [, , troisieme] = couleurs; // sauter des éléments
const [first, ...rest] = couleurs;
// first = "rouge", rest = ["vert", "bleu"]Destructuring dans les paramètres de fonction
function afficherProfil({ nom, age, ville = "inconnu" }) {
console.log(`${nom}, ${age} ans, ${ville}`);
}
afficherProfil({ nom: "Alice", age: 25 });
// "Alice, 25 ans, inconnu"C'est un idiome puissant pour les fonctions qui prennent un seul objet configuration — la signature reste lisible même avec 5-6 options.
Cas pratique fil rouge
La fonction afficherProfil ci-dessus est exactement le genre d'utilitaire
que vous réutiliserez dans le projet fil rouge (séance 5, Node.js) pour
formater des objets utilisateur avant de les sérialiser en JSON.
🛠️ Exercices pratiques
Créer un objet et utiliser la destructuration avancée
Créer et manipuler des objets JavaScript
Vous allez implémenter des fonctions qui retournent des objets, formattent des chaînes et appliquent la destructuration avancée (renommage, valeur par défaut, reste).
- Créer un objet littéral avec la syntaxe raccourcie
- Utiliser une template literal pour formater une chaîne
- Combiner renommage, valeur par défaut et reste dans une destructuration
Partie A — Créer un objet
Créez une fonction creerPersonne(nom, age, email) qui retourne un objet avec ces trois propriétés.
Partie B — Formater une présentation
Écrivez presentation(nom, age) qui retourne la phrase exacte : Bonjour, je m'appelle [nom], j'ai [age] ans.
Partie C — Destructuration avancée
Écrivez extraireDonnees(personne) qui utilise la destructuration pour :
- extraire
nomet renommerageenageAnnee - définir
emailpar défaut à'non-communique'si absent - récupérer le reste des propriétés dans
autresInfos - retourner
{ nom, ageAnnee, email, autresInfos }
Indice — destructuration combinée
Combinez renommage (age: ageAnnee), valeur par défaut (email = "non-communique") et reste (...autresInfos) dans une seule destructuration : const { nom, age: ageAnnee, email = "non-communique", ...autresInfos } = personne.
Piège fréquent — email absent
Si l'objet personne ne contient pas la clé email, la valeur par défaut doit s'appliquer. Sans = "non-communique" dans la destructuration, email vaudrait undefined.
Code à valider
🧩 Synthèse du bloc
Création d'objets
Littéral, Object.create, constructeur/new — choisir selon réutilisation et besoin de prototype.
var / let / const
var = portée fonctionnelle, hoisting à undefined. let/const = bloc + TDZ. Privilégier const, puis let.
Fermetures
Une fonction capture son scope englobant. Utiles pour l'encapsulation, les factories, les callbacks.
Destructuration
Extraction élégante depuis objets et tableaux, avec renommage, défauts, et rest. On l'utilise dans les params de fonction.
Quiz de fin de bloc
Quiz du chapitre
JavaScript avancé
Terminez le quiz du chapitre pour le marquer comme complété.