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. C'est ce mécanisme qui rend possible les callbacks, les HOF, 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. « 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). C'est pour ça que les event handlers, les callbacks réseau et les timers fonctionnent : ils capturent tous un morceau de contexte au moment où ils sont créés.
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 s'écrit SCRIPTS.filter(s => s.living).map(s => s.year). Choisir, 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.
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, fait des conversions de types automatiques, et ne plante pas là où d'autres langages lanceraient une erreur. Oubliez let devant une variable : vous venez de créer une globale en silence. 0 == false retourne true. Un NaN produit par une opération invalide se propage sans message jusqu'à produire un résultat faux à l'affichage. Haverbeke nomme ces pièges clairement et présente les solutions (strict mode, 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 "attendre" une requête réseau en bloquant tout. La solution historique : les callbacks. Vous passez une fonction à exécuter quand la réponse arrive. Le problème : imbriquer 5 callbacks pour séquencer 5 opérations produit une pyramide illisible. Les Promises ont résolu l'imbrication : .then().then().catch() s'enchaîne à plat. async/await va plus loin : vous écrivez du code qui ressemble à du synchrone, et le moteur gère les Promises dessous. La citation du livre résume bien ce que ça change : « une fonction async peut, dans son corps, attendre d'autres Promises d'une façon qui ressemble à du synchrone » (p. 283). Avant, vous chaîniez des callbacks ou des .then() ; maintenant vous écrivez const data = await fetch(url) comme si la réponse était immédiate.
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. Haverbeke appelle la version modulaire « 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). 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.
Trois choses que je ne savais pas avant de le lire
- Haverbeke utilise une corneille nommée Carla pour enseigner la programmation asynchrone. Elle pirate un WiFi par timing attack : tester chaque chiffre du code et mesurer la rapidité du rejet. Tout le chapitre 11 se déroule à travers ce récit absurde : callbacks, Promises et async/await s'enchaînent naturellement dans la même histoire sans rupture.
- En trois pages, Haverbeke montre que
sum(range(1, 10))et sa version en binaire calculent la même chose — mais l'une se lit, l'autre pas. C'est l'argument du livre entier : un langage qui permet de nommer des concepts change ce qu'on peut raisonner dessus. - La licence du livre est Creative Commons. Haverbeke publie gratuitement parce qu'il pense que c'est la bonne chose à faire. Il vend une version papier avec un chapitre bonus pour ceux qui veulent soutenir le travail. Ce modèle a maintenu le livre vivant quinze ans.
Mon avis, honnêtement
Les douze premiers chapitres construisent leur progression dans le bon ordre : fonctions comme valeurs d'abord (le concept qui débloque tout), closures ensuite (ce qu'on fait avec), puis filter/map/reduce (comment les composer), enfin les prototypes (pourquoi this se comporte ainsi). Chaque concept repose sur le précédent sans brûler d'étape. Les exercices ne demandent pas de reproduire un exemple : ils posent un problème original qui oblige à assembler soi-même ce qu'on vient de lire.
Les chapitres 13 à 19 (DOM, Canvas, jeu de plateforme) sont exacts mais moins essentiels : si votre objectif est de comprendre les fondamentaux JS, vous pouvez les lire en diagonale — les 12 premiers chapitres suffisent. Le projet de jeu de plateforme en ch.16 est bien fait, mais il demande trois chapitres pour être construit.
En 2026, JS reste le seul langage natif dans tous les navigateurs et l'IA en génère beaucoup. Comprendre les closures et la chaîne de prototypes, c'est ce qu'il faut pour relire du code généré et repérer les comportements inattendus. React repose lui-même sur les closures (les hooks capturent l'état) et le prototype chain — comprendre ces fondamentaux aide à débugger React, pas seulement du JS vanilla. Et le livre qui explique tout ça est gratuit depuis quinze ans.
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,
thisou 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)