TW3 — Technologies du Web 3

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; // true

Un 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.

varletconst
Portéefonctionbloc { ... }bloc { ... }
Hoistingoui (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 :

  • const par défaut — le littéral ne sera jamais réassigné
  • let quand 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(); // 3

Chaque 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)) capture id

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 nom et renommer age en ageAnnee
  • définir email par 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

javascript

🧩 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

4 questions
0 / 4 répondue0%
  1. 1Quels sont les deux grands groupes de types en JavaScript ?
  2. 2Comment déclarer une variable modifiable actuellement recommandée ?
  3. 3Que fait la destructuration d'objet ?
  4. 4À quoi sert une fonction fléchée (arrow function) ?
Répondez à toutes les questions pour valider.

JavaScript avancé

Terminez le quiz du chapitre pour le marquer comme complété.

Tableau de bord

On this page