Bibliothèque · Résumé et avis

Eloquent JavaScript

De Marijn Haverbeke. Gratuit en ligne, à jour ES2024, et probablement le livre JavaScript le plus honnête jamais écrit.

FR EN
Couverture d'Eloquent JavaScript, Marijn Haverbeke

Eloquent JavaScript

Eloquent JavaScript: A Modern Introduction to Programming

8.8 /10

« Gratuit, à jour, honnête : il n'y a aucune raison de ne pas le lire. »

  • AuteurMarijn Haverbeke
  • Édition4e éd. 2024 · 456 pages
  • ÉditeurNo Starch Press
  • En ligneeloquentjavascript.net · gratuit
  • Fiche~9 min de lecture
Notation du livre sur 5 dimensionsIdées9/10Applicable9/10Lisibilité9/10Actualité9/10Exemples8/10

L'introduction à JavaScript la plus honnête, disponible gratuitement en ligne. Mise à jour ES2024.

Pourquoi ce livre

Eloquent JavaScript est en ligne gratuitement depuis 2011. Haverbeke le met à jour à chaque version majeure d'ECMAScript, sans exception : la quatrième édition couvre ES2024. La plupart des livres de programmation prennent la poussière ; celui-là est un document vivant depuis quinze ans.

Mais ce qui le distingue, ce n'est pas le prix ni la mise à jour. C'est le ton. Haverbeke ouvre l'introduction en avouant avoir rapidement détesté JavaScript. Puis, quelques pages plus loin, qu'il a fini par l'aimer. Cette trajectoire, c'est tout le livre : partir d'une confusion honnête, la traverser jusqu'à une vraie compréhension. Il vous montre le binaire, puis l'assembleur, puis le JS. Et vous comprenez pourquoi les langages existent.

Les idées qui restent

1Un programme est une construction de pensée

L'introduction montre le même programme (additionner les entiers de 1 à 10) en binaire brut, puis en pseudo-assembleur lisible, puis en boucle while JavaScript, puis en sum(range(1, 10)). La morale est explicite : « un bon langage de programmation permet au développeur de parler des actions à effectuer à un niveau plus élevé » (p. 8). Ce cadrage, posé tôt et illustré concrètement, répond mieux à la question "pourquoi les langages existent" que beaucoup de cours de CS entiers.

2Les fonctions sont des valeurs : la vraie rupture

Dans la plupart des langages, une fonction est une entité spéciale qu'on ne peut pas manipuler comme une donnée. En JavaScript, ce n'est pas le cas : une fonction se stocke dans une variable, se passe en argument, se retourne depuis une autre fonction. Haverbeke illustre ça en stockant une fonction dans launchMissiles, puis en la réassignant à une no-op selon une condition :

let launchMissiles = () => { /* vrai lancement */ };
if (safeMode) {
    launchMissiles = () => {}; // remplacée par une no-op
}
launchMissiles(); // ne fait rien en mode sécurisé

C'est ce mécanisme qui rend possible les callbacks, les fonctions d'ordre supérieur, et les closures des chapitres suivants.

3Les closures : l'environnement voyage avec la fonction

Sans closure, une fonction interne perd ses variables dès que la fonction parente se termine. JavaScript fait le contraire : multiplier(2) retourne une fonction qui multiplie par 2, et cette fonction conserve l'accès à factor = 2 même après la fin de multiplier :

function multiplier(factor) {
    return number => number * factor;
}
let double = multiplier(2);
double(5); // 10, factor est toujours accessible

« Un bon modèle mental est de penser que les fonctions contiennent à la fois le code de leur corps et l'environnement dans lequel elles ont été créées » (p. 72). Ce mécanisme est derrière :

  • les event handlers (ils capturent l'élément DOM ou l'état au moment de leur création) ;
  • les factory functions (chaque appel produit une nouvelle fonction avec son propre état privé) ;
  • l'application partielle (fixer certains arguments maintenant, fournir le reste plus tard) ;
  • une large partie des packages npm (la plupart des librairies utilitaires ne sont que des closures sur une configuration).

4filter, map, reduce : penser par transformations

Le chapitre 5 utilise un dataset de systèmes d'écriture humains (latin, arabe, han...) pour illustrer les fonctions d'ordre supérieur. Haverbeke compare deux recettes de soupe aux pois : l'une liste chaque geste étape par étape ; l'autre dit juste "faire tremper, mijoter, hacher". Même résultat, mais la seconde exige qu'on connaisse le vocabulaire.

En code, c'est pareil : calculer l'âge moyen des alphabets vivants tient en une expression lisible :

SCRIPTS.filter(s => s.living).map(s => s.year)

Sélectionner, transformer, agréger. C'est ce que ça veut dire penser par transformations.

5Les prototypes et le vrai sens de this

Les objets JS sont liés à d'autres objets via une chaîne de prototypes : quand une propriété est absente, le runtime remonte la chaîne jusqu'à la trouver ou atteindre null. Object.getPrototypeOf([]) == Array.prototype vaut true : voilà pourquoi vos tableaux ont .map() sans que vous les ayez définis.

Le chapitre explique aussi pourquoi this dans une arrow function pointe vers le contexte lexical, alors que dans une fonction classique il dépend de l'appelant. C'est la confusion la plus fréquente dans les callbacks JS.

La chaîne de prototypes monTableau [0, 1, 2] Array.prototype .map() .filter() .reduce() Object.prototype .toString() .hasOwn() Quand .map() est introuvable sur monTableau → on cherche sur Array.prototype → trouvé. monObjet = {} objet littéral Object.prototype null Tout objet remonte jusqu'à Object.prototype, puis null. Chaque tableau a aussi Object.prototype.
La recherche d'une propriété remonte la chaîne jusqu'à null

6JavaScript est permissif par conception : avantages et pièges

JS a été conçu pour être tolérant : il exécute du code approximatif sans se plaindre, convertit les types tout seul, et ne plante pas là où d'autres langages lanceraient une erreur. Pratique pour démarrer, piégeux à grande échelle :

compteur = 0          // oubli de "let" : globale créée EN SILENCE
0 == false            // true (conversion automatique)
0 === false           // false (=== ne convertit pas : à préférer toujours)
"5" - 1               // 4  ("5" devient nombre)
"5" + 1               // "51" (1 devient texte !) : le piège classique

Un NaN (« not a number », le résultat d'une opération invalide comme "abc" * 2) se propage ensuite sans message jusqu'à un affichage faux. Haverbeke nomme ces pièges clairement et présente les parades (le mode strict, === systématique, TypeScript) sans les vendre comme des panacées.

7De callback hell à async/await : l'évolution de l'asynchrone

JS tourne sur un seul thread : il ne peut pas bloquer en attendant une réponse réseau sans figer toute la page. Le chapitre retrace l'histoire complète des solutions :

  • Les callbacks : vous passez une fonction à exécuter quand la réponse arrive. Simple, mais imbriquer cinq callbacks pour séquencer cinq opérations produit une pyramide illisible.
  • Les Promises : un reçu pour une valeur future. L'imbrication disparaît : .then().then().catch() s'enchaîne à plat. Les erreurs se propagent automatiquement.
  • async/await : du sucre syntaxique sur les Promises qui ressemble à du code synchrone. const data = await fetch(url) semble immédiat ; le moteur gère la Promise dessous.

« Une fonction async peut, dans son corps, attendre d'autres Promises d'une façon qui ressemble à du synchrone » (p. 283). Il faut quand même comprendre les Promises pour déboguer ce qui coince, mais async/await est là où on vit au quotidien.

8Les modules : des LEGO plutôt que de la boue

Avant les ES modules (2015), tout le JavaScript tournait dans une portée globale partagée : deux scripts pouvaient écraser les variables l'un de l'autre sans avertissement. Le module renverse ça : chaque fichier choisit ce qu'il expose et ce qu'il emprunte.

// panier.js : ce fichier décide de ce qui sort, le reste reste privé
export function total(lignes) { ... }
const TVA = 0.2                 // invisible dehors : pas de collision possible

// facture.js : on emprunte par son nom, le connecteur bien défini
import { total } from './panier.js'

Haverbeke appelle ça « du LEGO, où les pièces interagissent via des connecteurs bien définis, plutôt que de la boue où tout se mélange » (p. 250) : export et import sont ces connecteurs. npm arrive avec plus de trois millions de packages ; « une bonne partie est de la camelote, pour être honnête » (p. 254). Cette franchise sur l'écosystème est caractéristique du ton du livre.

À gauche, un château bien construit en briques emboîtables ; à droite, un tas de boue où des objets sont à moitié engloutis
Les modules selon Haverbeke : des connecteurs bien définis, plutôt que de la boue où tout se mélange.

Trois choses que je ne savais pas avant de le lire

Une corneille perchée sur une antenne de toit, un ordinateur portable sous l'aile et un chronomètre flottant, face à une maison qui émet du WiFi
Carla, la corneille du chapitre 11, en plein audit du WiFi pavillonnaire (chronomètre en main).

Mon avis, honnêtement

Haverbeke a un argument de vente que personne d'autre n'a : il avoue avoir détesté JavaScript avant de l'aimer (p. 9). Il part donc exactement d'où vous partez. Et ses douze premiers chapitres montent dans le bon ordre : fonctions comme valeurs, closures, filter/map/reduce, prototypes. Chaque concept s'appuie sur le précédent, et les exercices ne demandent pas de recopier : ils vous laissent vous débrouiller, et c'est là qu'on apprend.

Les chapitres navigateur (13 à 19) sont corrects mais moins essentiels : si votre but est de comprendre JS, les douze premiers suffisent. Le jeu de plateforme du chapitre 16 est sympa, mais trois chapitres pour un jeu, c'est un investissement. Lecture en diagonale autorisée, je ne le dirai à personne.

En 2026, l'IA génère du JavaScript au kilomètre, et c'est exactement pour ça qu'il faut comprendre les closures et la chaîne de prototypes : c'est ce qui permet de relire ce code et d'y repérer les surprises. React lui-même n'est que des closures bien habillées (les hooks capturent l'état). Et le livre qui explique tout ça est gratuit depuis quinze ans. Il n'y a littéralement pas d'excuse.

Odilon

Toujours valable en 2026 ?

La 4e édition date de 2024 et couvre ES2024 : propriétés privées (#property), optional chaining (obj?.prop), structuredClone, top-level await : tout y est. Les fondamentaux (closures, prototypes, event loop) sont aussi pertinents qu'à la sortie, parce que les frameworks sont construits par-dessus. La seule partie qui vieillit est la section DOM/navigateur : exacte, mais moins représentative du frontend moderne.

Pour qui ?

Lisez-le si

  • Vous écrivez du JavaScript mais avez l'impression de deviner pourquoi les closures, this ou les Promises se comportent ainsi
  • Vous débutez et voulez un seul livre qui vous emmène du zéro au Node.js, gratuitement
  • Vous relisez du JS généré par IA et voulez un cadre solide pour le juger
  • Vous aimez les livres qui vous traitent en adulte : pas de simplifications excessives, de vrais exercices

Passez si

  • Vous comprenez déjà les closures, la chaîne de prototypes et l'event loop : vous le saurez dès le chapitre 3
  • Vous cherchez une référence qu'on consulte par index : la MDN remplit mieux ce rôle
  • Vous cherchez React, Vue, ou TypeScript spécifiquement : ce livre ne couvre pas les frameworks ni le JS typé

Pour aller plus loin

Les chapitres sur les closures et les prototypes se pratiquent directement dans le cours JavaScript de ce site. Pour TypeScript (la couche typée au-dessus de JS), Effective TypeScript de Dan Vanderkam est la suite logique. Pour les patterns async en pratique, le cours API REST couvre fetch et async/await dans un contexte réel.

Commentaires (0)

Voir toute la bibliothèque

D'autres fiches arrivent : un livre à la fois, la substantifique moelle seulement.