Esc
 Naviguer  Ouvrir Esc Fermer
Aller au contenu

6.1 — JavaScript essentiel

Débutant 40 min prérequis : axe 5 (HTML/CSS) lu

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

JavaScript a 7 types primitifs + objets.

PrimitifExemple
string"hello", 'hello', `hello ${name}`
number42, 3.14, Infinity, NaN
booleantrue, false
undefinedvariable non initialisée
nullabsence intentionnelle
symbolidentifiant unique (avancé)
bigint42n (entiers > 2⁵³)

Tout le reste est un objet : tableaux ([]), fonctions, dates, regex, classes…

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 objet

C’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); // 0

Solution moderne :

// Spread pour copier
const copie = { ...original };
// Tableau
const copieTab = [...original];
// Profondeur arbitraire
const profondCopie = structuredClone(original); // depuis Node 17 / browsers récents
1 == "1" // true ← coercion implicite
1 === "1" // false ← compare aussi le type
null == undefined // true
null === undefined // false

Règle absolue : utilise toujours === (et !==). Les seules exceptions justifiées sont rares (genre tester null ou undefined en une fois : value == null).

var x = 1; // ❌ ancienne syntaxe, scope fonction
let y = 2; // ✅ scope bloc, réassignable
const z = 3; // ✅ scope bloc, NON réassignable
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 arr = [1, 2, 3];
arr.push(4); // OK, le contenu peut muter
arr = []; // ❌ erreur, on réassigne la variable

Si tu veux figer l’objet :

Object.freeze(arr);
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.

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

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 undefined

Règle pratique : pour les callbacks et les méthodes passées en référence, utilise une arrow.

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(); // 1
c.increment(); // 2
c.get(); // 2
// "count" est devenu privé : impossible d'y accéder de l'extérieur

Toute fonction en JS qui utilise une variable d’un scope parent crée une closure. C’est l’équivalent du privé en POO.

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"
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"
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éduction
nums.reduce((acc, n) => acc + n, 0); // 15
nums.reduce((acc, n) => Math.max(acc, n), -Infinity); // 5
// Recherche
nums.find(n => n > 3); // 4
nums.findIndex(n => n > 3); // 3
nums.includes(2); // true
nums.some(n => n < 0); // false
nums.every(n => n > 0); // true
// Tri (mute le tableau original — attention !)
[...nums].sort((a, b) => b - a); // copie, puis tri décroissant
// Itération
nums.forEach(n => console.log(n));
// Concaténation
[...nums, 6, 7]; // immutable
nums.concat([6, 7]);
// Création
Array.from({ length: 5 }, (_, i) => i); // [0, 1, 2, 3, 4]
Array(3).fill(0); // [0, 0, 0]
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 objets

Règle : for…of pour itérer une valeur, for…in pour les clés d’un objet (rare).

// Tableau
const [a, b, c] = [1, 2, 3];
const [first, ...rest] = [1, 2, 3, 4]; // rest = [2, 3, 4]
// Objet
const { name, age } = { name: 'Alice', age: 30 };
// Renommer
const { name: prenom } = { name: 'Alice' };
// Valeur par défaut
const { theme = 'light' } = options;
// Imbriqué
const { user: { email } } = data;
// Dans les paramètres de fonction
function greet({ name, age = 0 }) {
return `${name}, ${age} ans`;
}
// 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 }
// nommé
export const PI = 3.14;
export function double(x) { return x * 2; }
// default (un seul par fichier)
export default class App {}
// ré-exporter
export { foo, bar } from './other.js';
import App from './app.js'; // default
import { PI, double } from './math.js'; // nommés
import { PI as Pi } from './math.js'; // renommer
import * as Math from './math.js'; // tout dans un namespace
import './side-effect.js'; // juste exécuter le fichier
// Dynamique (lazy)
const module = await import('./heavy.js');
// 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 (?.)
user?.profile?.email // undefined si user ou profile est null/undefined
// Avec appel
user?.greet?.() // appelle greet si elle existe
// Avec index
arr?.[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 3000
Tu as `const arr = [1, 2, 3]; arr.push(4); console.log(arr);`. Que se passe-t-il ?
Quelle ligne affiche [1, 2, 3] ?
`const port = process.env.PORT || 3000`. Quel piège ?
  • 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.