JavaScript ES6+ â Guide pratique
Syntaxe moderne de JavaScript (ES2015 et au-delĂ ) â let/const, flĂšches, dĂ©structuration, spread/rest, modules ES, Promises, async/await, optional chaining et nullish coalescing.
Cette page est un complément à Frontend. Elle se concentre sur les mécanismes de langage ES6+.
let et const â remplacement de var
var déclare une variable portée au bloc le plus proche fonction, pas au bloc if/for/while. let et const sont portés au bloc { ... }.
// var â portĂ©e fonction, pas de bloc
function demoVar() {
if (true) {
var x = 10;
}
console.log(x); // 10 â visible hors du bloc
}
// let / const â portĂ©e bloc
function demoBlock() {
if (true) {
let y = 10;
const z = 20;
}
console.log(y); // ReferenceError
console.log(z); // ReferenceError
}Pitfall :
vardans une boucleforcrĂ©e un seul binding partagĂ© â les closures captent la mĂȘme variable. Utiliserletpour la boucle dans ce cas.
Dead zone (TDZ)
Une variable let/const existe avant son initialisation, mais son accĂšs lĂšve ReferenceError jusquâĂ la dĂ©claration.
console.log(a); // ReferenceError (TDZ)
let a = 10;
console.log(a); // 10
// Fonctionne â const est initialisĂ© AVANT d'ĂȘtre utilisĂ©
const b = 42;
console.log(b); // 42Pitfall :
constsignifie « liaison constante », pas « valeur constante ». Lâobjet liĂ© peut ĂȘtre mutĂ©.
const tab = [];
tab.push(1); // OK â la rĂ©fĂ©rence ne change pas
tab = []; // TypeError : Assignment to constant variableFonctions fléchées
Syntaxe courte pour les fonctions. Deux différences fondamentales avec function classique :
- Pas de
thispropre â elles hĂ©ritent duthisdu contexte lexical (celui du parent). - Pas de
argumentsâ le mot-clĂ©argumentsnâexiste pas dans une flĂ©chĂ©e.
// Fonction classique â this liĂ© Ă l'objet appelant
const obj = {
nom: 'Arthur',
saluer: function() {
return `Bonjour, je suis ${this.nom}`;
},
// Fonction flĂ©chĂ©e â this hĂ©ritĂ© (globale ici, undefined en mode strict)
saluerFléchée: () => {
return `Bonjour, je suis ${this.nom}`; // undefined
}
};
// Usage pratique : callback avec `this` préservé
class Compteur {
constructor() {
this.valeur = 0;
// setInterval avec fléchée : `this` reste le compteur
setInterval(() => { this.valeur++; }, 1000);
}
}RÚgle simple : utiliser une fléchée pour les callbacks et les méthodes sans besoin de
this. RĂ©serverfunctionclassique pour les mĂ©thodes dâobjet et les constructeurs.
Pitfall : les flĂ©chĂ©es ne peuvent PAS ĂȘtre utilisĂ©es comme constructeurs.
new (() => {})lĂšveTypeError.
Déstructuring
Extraire des valeurs dâobjets et de tableaux avec une syntaxe expressive.
Objets
const config = { host: 'localhost', port: 3000, debug: true };
// Extraire avec renommage
const { host: h, port: p, debug } = config;
// h = 'localhost', p = 3000, debug = true
// Valeurs par défaut (uniquement pour `undefined`)
const { timeout = 5000, retries = 3 } = config;
// timeout = 5000, retries = 3 (config n'a pas ces clés)
// Capturer le reste avec spread
const { debug, ...sansDebug } = config;
// sansDebug = { host: 'localhost', port: 3000 }Tableaux
const couleurs = ['rouge', 'vert', 'bleu'];
// Extraire des positions spécifiques
const [, milieu, fin] = couleurs;
// milieu = 'vert', fin = 'bleu'
// Capturer le reste
const [premier, ...lesAutres] = couleurs;
// premier = 'rouge', lesAutres = ['vert', 'bleu']
// Ăchanger deux variables (sans variable temporaire)
let a = 1, b = 2;
[a, b] = [b, a];
// a = 2, b = 1Imbriquée
const réponse = {
données: {
utilisateurs: [
{ nom: 'Alice', Ăąge: 30 },
{ nom: 'Bob', Ăąge: 25 }
],
meta: { page: 1, total: 42 }
}
};
const {
données: { utilisateurs: list, meta: { page } }
} = réponse;
list[0].nom; // 'Alice'
page; // 1Pitfall : déstructurer une valeur
nullouundefinedlÚveTypeError. Toujours protéger :const { x } = obj ?? {};ouconst { x } = (obj || {});.
Spread (...) et opérateurs rest
Le mĂȘme syntaxe ... a deux usages distincts selon le contexte.
Spread â « Ă©tendre » un itĂ©rable
// Tableaux
const combiné = [...tableauA, ...tableauB];
const copié = [...original];
// Objets (shallow merge, derniÚres clés écrasent)
const combinéObj = { ...cible, ...origine };
// Si les deux ont la mĂȘme clĂ©, origine gagne.
// Passer un tableau comme arguments
const max = Math.max(...[3, 1, 4, 1, 5]);Rest â « capturer le reste » dans une dĂ©claration
// Déstructuring objet
const { password, ...user } = donnéesUtilisateur;
// user = tout sauf password
// Déstructuring tableau
const [premier, ...reste] = [1, 2, 3, 4];
// reste = [2, 3, 4]
// ParamĂštres variadiques
function somme(...nombres) {
return nombres.reduce((acc, n) => acc + n, 0);
}
somme(1, 2, 3); // 6Différence clé : le spread « démonte » un tableau/objet en éléments individuels ; le rest « monte » des éléments en un tableau/objet unique.
Template literals
ChaĂźnes multi-lignes et interpolation de expressions avec le backtick `.
const nom = 'Arthur';
const Ăąge = 30;
// Interpolation
const salutation = `Bonjour, je suis ${nom}, ${Ăąge} ans.`;
// Multi-lignes (sans `\n` explicites)
const message = `
Ligne 1
Ligne 2
Ligne 3
`;
// Expression complĂšte dans ${ }
const arr = [1, 2, 3];
const résumé = `Le tableau contient ${arr.length} éléments : ${arr.join(', ')}.`;
// 'Le tableau contient 3 éléments : 1, 2, 3.'Tagged templates
Appeler une fonction personnalisée pour traiter le template. Utile pour le formatage ou la sécurité (échappement HTML).
// Fonction tag : reçoit les parties de chaßne et les expressions
function escapeHTML(strings, ...valeurs) {
return strings.reduce((resultat, partie, i) => {
const val = i < valeurs.length
? String(valeurs[i]).replace(/</g, '<').replace(/>/g, '>')
: '';
return résultat + partie + val;
}, '');
}
const user = '<script>alert("xss")</script>';
const sécurisé = escapeHTML`Bienvenue, ${user} !`;
// 'Bienvenue, <script>alert("xss")</script> !'Modules ES (import / export)
Remplacement de require() (CommonJS) et module.exports. Syntaxe déclarative, analyse statique possible, support natif dans tous les navigateurs modernes.
// module.js â Exportations
export const PI = 3.14159;
export function aire(rayon) {
return PI * rayon * rayon;
}
// Export nommé par défaut
export default function Racine(r) {
return Math.sqrt(r);
}// autre-module.js â Importations
// Importation spécifique
import { PI, aire } from './module.js';
// Renommer Ă l'import
import { PI as Pi } from './module.js';
// Import par défaut
import Racine from './module.js';
// Importer les deux en mĂȘme temps
import Racine, { PI, aire } from './module.js';
// Importer TOUT dans un namespace
import * as maths from './module.js';
maths.PI;
maths.aire(5);
// Import dynamique (chargement tardif)
import('./module.js').then(m => {
m.aire(10);
});Import dynamique vs statique : les
importstatiques sont rĂ©solus au chargement du module. Les imports dynamiques (import()) retournent une Promise â utiles pour le code lazy-loaded (routes, plugins).
Pitfall : les exports
defaultne sont pas verrouillĂ©s par le linter. Un mĂȘme module ne peut avoir quâun seulexport default.
Promises et async/await
Promise â pattern asynchrone
Une Promise représente une opération asynchrone en trois états : pending, fulfilled, rejected.
// Création manuelle (rare)
const p = new Promise((résoudre, rejetter) => {
if (donnéesValides) {
résoudre(données);
} else {
rejetter(new Error('Données invalides'));
}
});
// ChaĂźnage `.then()` / `.catch()`
chargerDonnées()
.then(traiter)
.then(afficher)
.catch(erreur => console.error(erreur));async/await â syntaxe synchronisĂ©e
async dĂ©clare une fonction qui retourne implicitement une Promise. await suspend lâexĂ©cution jusquâĂ ce que la Promise soit rĂ©solue.
async function chargerEtAfficher() {
try {
const users = await fetch('/api/users').then(r => r.json());
const posts = await fetch('/api/posts').then(r => r.json());
console.log(users, posts);
} catch (erreur) {
console.error('Erreur:', erreur.message);
}
}
chargerEtAfficher();Parallélisation
await séquentiel = somme des durées. Promise.all() = durée du plus long.
// Séquentiel (lent)
const a = await fetch('/api/a'); // 200ms
const b = await fetch('/api/b'); // 300ms
// Total : ~500ms
// ParallĂšle (rapide)
const [a, b] = await Promise.all([
fetch('/api/a'),
fetch('/api/b')
]);
// Total : ~300ms (le plus long des deux)
// Si un seul échoue, toute la chaßne échoue
const résultat = await Promise.allSettled([
fetch('/api/a'),
fetch('/api/échec')
]);
// Pour inspecter chaque résultat sans échouer brutalementPitfall :
awaitne fait pas planter la fonction â il rejette laPromiseretour. Capturer avectry/catchou.catch()pour Ă©viter unUnhandled Promise Rejection.
Optional chaining (?.) et nullish coalescing (??)
Optional chaining
Accéder à une propriété ou appeler une méthode sans lever TypeError si la valeur intermédiaire est null/undefined.
const utilisateur = {
profil: {
nom: 'Alice',
adresse: { ville: 'Paris' }
}
};
// Sans optional chaining :
utilisateur.profil.adresse.codePostal; // undefined (pas d'erreur)
utilisateur.inconnu.clef; // TypeError !
// Avec optional chaining :
utilisateur.profil?.nom; // 'Alice'
utilisateur.inconnu?.clef; // undefined (pas d'erreur)
utilisateur.profil?.adresse?.ville; // 'Paris'
// Appel de méthode sécurisé
const résultat = utilisateur.fetcher?.(données);
// si fetcher est undefined, résultat = undefined (pas d'erreur)Nullish coalescing
Retourne le cÎté droit si la gauche est null ou undefined (pas si false, 0, ou '').
// OpĂ©rateur `||` â falsy (faux, 0, '', null, undefined)
const message = '' || 'dĂ©faut'; // 'dĂ©faut' â souvent indĂ©sirable
// OpĂ©rateur `??` â nullish uniquement
const message = '' ?? 'dĂ©faut'; // '' â prĂ©servĂ©
const valeur = null ?? 42; // 42
const zéro = 0 ?? 42; // 0
// ChaĂźnage avec optional chaining
const hauteur = objet?.dimensions?.hauteur ?? 100;Différence clé :
||remplacefalse,0,'';??ne remplace quenulletundefined.
RĂ©capitulatif â quand utiliser quoi
| Besoin | Solution ES6+ |
|---|---|
| Variable bloc | let / const (jamais var) |
Méthode simple, pas de this | Fonction fléchée |
MĂ©thode dâobjet, this nĂ©cessaire | function classique |
| Extraire des valeurs | Déstructuring |
| Fusionner / cloner | Spread ... |
| ParamĂštres variables | Rest ...args |
| ChaĂźne avec variables | Template literal ` |
| Module structurel | import / export |
| Code asynchrone | async / await |
| AccÚs sûr à propriété | Optional chaining ?. |
| Valeur par défaut sécurisée | Nullish coalescing ?? |
PiĂšges courants
| PiĂšge | SymptĂŽme | Correction |
|---|---|---|
const mutĂ© | TypeError Ă lâaffectation | Utiliser let si la rĂ©fĂ©rence change ; structuredClone() pour une copie profonde |
this dans flĂ©chĂ©e | this = undefined dans mĂ©thode dâobjet | Passer en function classique |
arguments dans fléchée | ReferenceError | Utiliser les paramÚtres rest ...args |
var dans une boucle | Closure captant la mĂȘme variable | Remplacer var par let |
Template literal avec \ à la fin | Espace blanc indésirable dans multi-lignes | Utiliser ${''} ou supprimer le \ |
Promise non-gérée | Unhandled Promise Rejection | Toujours ajouter .catch() ou utiliser async/await avec try/catch |
| Optional chaining sur le cĂŽtĂ© gauche dâune affectation | SyntaxError | Utiliser {}, objet placeholder ou mĂ©thode dâaffectation conditionnelle |