6.1 — JavaScript essentiel
Débutant
🎯 Objectif : maîtriser le langage JS au point que tu sais ce qui se passe quand un framework fait sa magie. Sans ça, React et compagnie restent des boîtes noires.
À l'issue de cet axe, tu sauras :
- Distinguer types primitifs vs objets, par valeur vs par référence
- Maîtriser var vs let vs const, hoisting, TDZ
- Écrire et expliquer une closure
- Comprendre prototype, this, classes
- Manier map, filter, reduce sans hésitation
- Importer/exporter avec les modules ES
💡 Termes glossaire utilisés dans cette section : closure , hoisting , prototype . Survole-les pour la définition rapide.
Types primitifs vs objets
Section intitulée « Types primitifs vs objets »JavaScript a 7 types primitifs + objets.
| Primitif | Exemple |
|---|---|
string | "hello", 'hello', `hello ${name}` |
number | 42, 3.14, Infinity, NaN |
boolean | true, false |
undefined | variable non initialisée |
null | absence intentionnelle |
symbol | identifiant unique (avancé) |
bigint | 42n (entiers > 2⁵³) |
Tout le reste est un objet : tableaux ([]), fonctions, dates, regex, classes…
Par valeur vs par référence
Section intitulée « Par valeur vs par référence »Les primitifs sont copiés :
let a = 5;let b = a;b = 10;console.log(a); // 5 — a n'a pas bougéLes objets sont partagés par référence :
const a = { count: 5 };const b = a;b.count = 10;console.log(a.count); // 10 — a et b pointent au même objetC’est la cause de bugs classiques : passer un objet à une fonction qui le modifie sans le copier.
function reset(obj) { obj.count = 0; // modifie l'original !}
const data = { count: 5 };reset(data);console.log(data.count); // 0Solution moderne :
// Spread pour copierconst copie = { ...original };
// Tableauconst copieTab = [...original];
// Profondeur arbitraireconst profondCopie = structuredClone(original); // depuis Node 17 / browsers récentsÉgalité — == vs ===
Section intitulée « Égalité — == vs === »1 == "1" // true ← coercion implicite1 === "1" // false ← compare aussi le typenull == undefined // truenull === undefined // falseRègle absolue : utilise toujours === (et !==). Les seules exceptions justifiées sont rares (genre tester null ou undefined en une fois : value == null).
var, let, const
Section intitulée « var, let, const »var x = 1; // ❌ ancienne syntaxe, scope fonctionlet y = 2; // ✅ scope bloc, réassignableconst z = 3; // ✅ scope bloc, NON réassignableLe piège classique de var
Section intitulée « Le piège classique de var »for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100);}// affiche : 3, 3, 3 (var fuit hors du for)
for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100);}// affiche : 0, 1, 2 (let est par bloc)var n’a aucun usage en code moderne. N’écris que let et const.
const ne fige pas l’objet
Section intitulée « const ne fige pas l’objet »const arr = [1, 2, 3];arr.push(4); // OK, le contenu peut muterarr = []; // ❌ erreur, on réassigne la variableSi tu veux figer l’objet :
Object.freeze(arr);Hoisting et TDZ
Section intitulée « Hoisting et TDZ »console.log(a); // undefined (var hoisted)var a = 5;
console.log(b); // ReferenceError (TDZ)let b = 5;let et const existent dans la zone temporellement morte (TDZ) avant leur déclaration. Tu ne peux pas y accéder. C’est sain.
Functions
Section intitulée « Functions »3 syntaxes
Section intitulée « 3 syntaxes »// Function declaration (hoisted)function add(a, b) { return a + b; }
// Function expression (pas hoisted)const add = function(a, b) { return a + b; };
// Arrow function (pas hoisted, lexical this)const add = (a, b) => a + b;const add = (a, b) => { return a + b; };Différence clé : this
Section intitulée « Différence clé : this »Dans une fonction classique, this dépend de comment la fonction est appelée. Dans une arrow, this est lexical (capturé à la définition).
class Counter { count = 0;
// ❌ "this" perdu si on passe la méthode comme callback incrementBad() { this.count++; }
// ✅ "this" reste l'instance incrementGood = () => { this.count++; };}
const c = new Counter();const fn = c.incrementBad;fn(); // erreur : this est undefinedRègle pratique : pour les callbacks et les méthodes passées en référence, utilise une arrow.
Closures
Section intitulée « Closures »Une closure = une fonction qui capture des variables de son scope englobant, et qui garde l’accès même après que le scope soit terminé.
function counter() { let count = 0; return { increment: () => ++count, get: () => count, };}
const c = counter();c.increment(); // 1c.increment(); // 2c.get(); // 2// "count" est devenu privé : impossible d'y accéder de l'extérieurToute fonction en JS qui utilise une variable d’un scope parent crée une closure. C’est l’équivalent du privé en POO.
Prototypes et classes
Section intitulée « Prototypes et classes »JavaScript est prototype-based. Chaque objet a un __proto__ qui pointe vers un autre objet (sa “classe parente”).
Syntaxe classique (à connaître mais peu utilisée)
Section intitulée « Syntaxe classique (à connaître mais peu utilisée) »function Animal(name) { this.name = name;}Animal.prototype.speak = function() { return `${this.name} fait du bruit`;};
const a = new Animal('Rex');a.speak(); // "Rex fait du bruit"Syntaxe class (sucre syntaxique moderne)
Section intitulée « Syntaxe class (sucre syntaxique moderne) »class Animal { constructor(name) { this.name = name; }
speak() { return `${this.name} fait du bruit`; }
// Champ privé (depuis 2022) #secret = 'caché';
// Méthode statique static create(name) { return new Animal(name); }}
class Dog extends Animal { speak() { return `${this.name} aboie`; }}
const rex = new Dog('Rex');rex.speak(); // "Rex aboie"Tableaux — les méthodes essentielles
Section intitulée « Tableaux — les méthodes essentielles »const nums = [1, 2, 3, 4, 5];
// Transformation (renvoie un nouveau tableau)nums.map(n => n * 2); // [2, 4, 6, 8, 10]nums.filter(n => n > 2); // [3, 4, 5]nums.flatMap(n => [n, n * 10]); // [1, 10, 2, 20, ...]
// Réductionnums.reduce((acc, n) => acc + n, 0); // 15nums.reduce((acc, n) => Math.max(acc, n), -Infinity); // 5
// Recherchenums.find(n => n > 3); // 4nums.findIndex(n => n > 3); // 3nums.includes(2); // truenums.some(n => n < 0); // falsenums.every(n => n > 0); // true
// Tri (mute le tableau original — attention !)[...nums].sort((a, b) => b - a); // copie, puis tri décroissant
// Itérationnums.forEach(n => console.log(n));
// Concaténation[...nums, 6, 7]; // immutablenums.concat([6, 7]);
// CréationArray.from({ length: 5 }, (_, i) => i); // [0, 1, 2, 3, 4]Array(3).fill(0); // [0, 0, 0]for…of vs for…in
Section intitulée « for…of vs for…in »const arr = ['a', 'b', 'c'];
for (const value of arr) console.log(value); // 'a', 'b', 'c' ✅
for (const key in arr) console.log(key); // '0', '1', '2' ⚠ pour objetsRègle : for…of pour itérer une valeur, for…in pour les clés d’un objet (rare).
Destructuration
Section intitulée « Destructuration »// Tableauconst [a, b, c] = [1, 2, 3];const [first, ...rest] = [1, 2, 3, 4]; // rest = [2, 3, 4]
// Objetconst { name, age } = { name: 'Alice', age: 30 };
// Renommerconst { name: prenom } = { name: 'Alice' };
// Valeur par défautconst { theme = 'light' } = options;
// Imbriquéconst { user: { email } } = data;
// Dans les paramètres de fonctionfunction greet({ name, age = 0 }) { return `${name}, ${age} ans`;}Spread et rest
Section intitulée « Spread et rest »// Spread (étaler)const merged = [...arr1, ...arr2];const cloned = { ...obj };const updated = { ...obj, age: 31 };
// Rest (rassembler)function sum(...nums) { // nums est un tableau return nums.reduce((a, b) => a + b, 0);}
const { a, ...rest } = { a: 1, b: 2, c: 3 }; // rest = { b: 2, c: 3 }Modules ES
Section intitulée « Modules ES »// nomméexport const PI = 3.14;export function double(x) { return x * 2; }
// default (un seul par fichier)export default class App {}
// ré-exporterexport { foo, bar } from './other.js';import App from './app.js'; // defaultimport { PI, double } from './math.js'; // nommésimport { PI as Pi } from './math.js'; // renommerimport * as Math from './math.js'; // tout dans un namespaceimport './side-effect.js'; // juste exécuter le fichier
// Dynamique (lazy)const module = await import('./heavy.js');CommonJS — l’ancien
Section intitulée « CommonJS — l’ancien »// CommonJS (Node legacy)const express = require('express');module.exports = { foo, bar };Préfère ESM dans tous les projets modernes ("type": "module" dans package.json).
Optional chaining et nullish coalescing
Section intitulée « Optional chaining et nullish coalescing »// Optional chaining (?.)user?.profile?.email // undefined si user ou profile est null/undefined
// Avec appeluser?.greet?.() // appelle greet si elle existe
// Avec indexarr?.[0] // arr[0] si arr existe
// Nullish coalescing (??)const name = input ?? 'Anonyme'; // 'Anonyme' SI input est null ou undefined // (différent de || qui réagit aux falsy : '', 0, false)
const port = process.env.PORT ?? 3000; // ✅const port = process.env.PORT || 3000; // ⚠ "0" deviendrait 3000Auto-évaluation
Section intitulée « Auto-évaluation »Pour aller plus loin
Section intitulée « Pour aller plus loin »- Eloquent JavaScript — Marijn Haverbeke (gratuit en ligne)
- You Don’t Know JS Yet — Kyle Simpson (gratuit, sur GitHub)
- MDN — Référence JavaScript — incontournable
- JavaScript.info — tutoriel exhaustif
Suite : 6.2 — Asynchronisme — Promises, async/await, event loop.