Parcours d’apprentissage web – Part IV : JavaScript, interactions et navigateur
Dans les articles précédents, nous avons posé les premières bases du web côté navigateur. Le HTML nous a servi à organiser le contenu d’une page. Les CSS nous ont permis de lui donner une forme, une mise en page et une adaptation aux différents écrans. Mais malgré cela, une page reste encore assez figée : elle s’affiche, mais elle ne réagit pas vraiment.
C’est précisément à ce moment qu’intervient JavaScript. Ce langage apporte une dimension supplémentaire : il permet à la page de répondre à une action, de modifier son contenu ou de récupérer des informations auprès d’autres ressources. C’est grâce à cela que nos pages, et surtout nos sites, peuvent progressivement devenir de véritables applications web.
À notre habitude, nous n’allons pas aborder l’apprentissage du code uniquement par sa syntaxe ou sa grammaire. Nous allons plutôt observer où JavaScript agit réellement : dans le navigateur, au contact de la page et de ses éléments. En partant de cette observation, il devient beaucoup plus simple de comprendre ce que fait le langage, comment l’utiliser et comment organiser le code pour qu’il reste clair et évolutif.
Le rôle réel de JavaScript dans un site web
Avant d’écrire la moindre ligne, il est important de comprendre pourquoi JavaScript existe. Contrairement au HTML qui structure et au CSS qui met en forme, JavaScript permet d’agir. Il introduit le comportement. Une page peut réagir à un clic, modifier son contenu, afficher ou masquer un élément, ou encore communiquer avec d’autres ressources. Si aujourd’hui tous les navigateurs le comprennent, ce ne fût pas le cas au début du web.
Au milieu des années 1990, Netscape introduit un langage de script dans son navigateur. Pendant son développement, il porte d’abord le nom de Mocha, puis devient LiveScript. Peu avant la sortie de Navigator 2, il est finalement renommé JavaScript afin de profiter de la popularité du langage Java. JavaScript n’a aucun lien direct avec le langage Java. Le nom a longtemps entretenu la confusion. Internet Explorer, de son côté, implémente rapidement sa propre version, appelée JScript, ce qui provoque des divergences entre navigateurs et nécessite la production de deux codes distincts en fonction du navigateur utilisé…
/* Exemple représentatif du JavaScript de la fin des années 1990
Les développeurs devaient souvent détecter le navigateur
afin d'utiliser l'API disponible dans celui‑ci. */
// Détection très simplifiée du navigateur
var isNetscape = (navigator.appName == "Netscape");
var isIE = (navigator.appName == "Microsoft Internet Explorer");
// Fonction qui modifie le contenu d'un élément selon le navigateur
function changeTexte() {
if (isNetscape) {
// Netscape 4 utilisait la notion de "layers"
// accessibles via document.layers
document.layers["zone"].document.write("Contenu modifié pour Netscape");
}
else if (isIE) {
// Internet Explorer utilisait l'API document.all
// pour accéder aux éléments de la page
document.all["zone"].innerHTML = "Contenu modifié pour Internet Explorer";
}
}Ce type de code, appelé browser sniffing, était courant à l’époque. Les différences d’implémentation entre navigateurs obligeaient souvent les développeurs à écrire plusieurs branches de code pour produire le même comportement.
Pour résoudre ce problème, le langage est standardisé par l’organisation ECMA sous le nom ECMAScript. Cette standardisation permet progressivement d’unifier les implémentations et d’offrir un socle commun à tous les navigateurs. C’est cette normalisation qui a permis l’essor de l’écosystème JavaScript et l’explosion des usages que nous connaissons aujourd’hui.
Des ressources pour découvrir et approfondir JavaScript
Comme pour HTML et CSS, la découverte de JavaScript ne repose pas uniquement sur la lecture d’une documentation ou sur l’apprentissage de règles isolées. Elle passe surtout par l’expérimentation, par l’observation du comportement du navigateur et par l’exploration progressive de ressources fiables qui permettent de comprendre le langage dans son contexte réel d’utilisation. De nombreux sites, ouvrages et documentations proposent aujourd’hui des explications solides et des exemples concrets ; les quelques références suivantes constituent ainsi de très bons points de départ pour accompagner cette découverte et continuer à approfondir la pratique du langage.
- La documentation de référence reste celle de MDN, dont la section consacrée à JavaScript constitue souvent le point d’entrée le plus sûr pour comprendre le fonctionnement du langage et les interfaces offertes par le navigateur.
- Mais l’apprentissage gagne aussi à être nourri par des lectures plus approfondies. Le livre en ligne Eloquent JavaScript propose par exemple une approche progressive du langage, mêlant théorie et pratique. De son côté, le site Human Who Codes explore plus en détail certains aspects du langage et de son évolution.
- Pour celles et ceux qui souhaitent rester dans une logique pédagogique structurée, la section Core Scripting du parcours d’apprentissage proposé par MDN offre également une progression claire autour de la manipulation du document et des interactions, Premiers pas en JavaScript.
- Enfin, le site JavaScript.info constitue une autre ressource très complète, souvent appréciée pour la clarté de ses explications et pour ses nombreux exemples.

Sur Puce & Média, plusieurs articles permettent également d’approfondir certains aspects du langage. L’article ES6 : écrire du JavaScript qui nous ressemble enfin ne cherche pas à passer en revue toutes les nouveautés d’ES6 ni à en faire une fiche technique. D’autres ressources le font déjà très bien. L’objectif est plutôt de se demander ce que ces évolutions changent lorsque l’on écrit du JavaScript au quotidien, et comment la syntaxe moderne peut aider à écrire un code plus clair sans transformer complètement notre manière de penser.
L’article Parcourir et manipuler des objets efficacement avec JavaScript montre quant à lui différentes manières d’explorer et transformer des structures de données en JavaScript, un point essentiel dès que l’on manipule des objets, des tableaux ou des réponses provenant d’APIs.
L’essentiel reste néanmoins de pratiquer et de comprendre progressivement comment JavaScript permet de transformer un site statique en interface interactive.
Explorer JavaScript directement dans le navigateur
JavaScript s’exécute directement dans le navigateur. C’est donc là que nous devons l’observer et commencer à l’explorer. Pour cela, les navigateurs modernes proposent un outil très précieux : la console. Elle permet d’écrire quelques instructions, d’observer immédiatement le résultat, et de comprendre progressivement ce que fait le langage.
Plutôt que de commencer par un projet complexe, il suffit d’ouvrir un navigateur, d’afficher n’importe quelle page web, puis d’ouvrir la console des outils de développement (généralement avec la touche F12, ou via le menu Outils de développement du navigateur). À partir de ce moment‑là, nous pouvons déjà dialoguer avec la page affichée, ou simplement utiliser la console comme un petit laboratoire JavaScript. Présentation détaillée de la console.
Une fois la console ouverte, il est déjà possible de saisir quelques instructions et d’observer la réponse immédiatement :
// Affiche un message simple dans la console du navigateur
console.log("Bonjour depuis la console");
// Récupère le titre de la page actuellement ouverte
let titre = document.title;
// Affiche le texte "Titre de la page :" suivi du titre récupéré
console.log("Titre de la page :", titre);
// Petite opération JavaScript exécutée directement dans la console
// La console renverra immédiatement le résultat du calcul
2 + 2
Utiliser des environnements d’expérimentation simples
À l’instar de ce que nous venons de faire dans la console, et avant même d’intégrer JavaScript dans notre projet, il peut être utile d’expérimenter dans des environnements isolés. Des espaces comme CodePen ou JSFiddle offrent un petit laboratoire directement dans le navigateur : on écrit quelques lignes, on observe le résultat, on corrige, puis on recommence.
Il existe bien sûr d’autres environnements similaires, par exemple JavaScript Playground, JS.do ou encore certains compilateurs en ligne comme Programiz, mais l’idée reste toujours la même : disposer d’un terrain d’expérimentation simple où tester rapidement une idée sans perturber le projet principal. Ces espaces deviennent des laboratoires. Nous pouvons essayer, observer, corriger, et recommencer. Un exemple très simple peut être testé dans l’un de ces environnements.
<button id="demo">Cliquer ici</button>
<script>
const bouton = document.getElementById("demo");
bouton.addEventListener("click", () => {
alert("Le navigateur exécute bien JavaScript.");
});
</script>
Comment JavaScript s’insère dans une page web
JavaScript peut être intégré directement dans un fichier HTML en employant les balises HTML <script>, ou placé dans un fichier séparé grâce à l’attribut de chargement src. Cette distinction permet déjà de comprendre la notion de séparation des responsabilités.
<!-- Première manière : écrire le code JavaScript directement dans la page -->
<script>
// Ce code est placé directement dans le document HTML
console.log("Script exécuté depuis la balise <script> intégrée dans la page");
</script>
<!-- Seconde manière : charger un fichier JavaScript externe -->
<script src="script.js"></script>
<!-- Dans ce cas, le navigateur charge et exécute le contenu du fichier script.js -->Le moment où un script est chargé dans une page n’est pas anodin. Un script placé dans l’élément head peut bloquer l’analyse du document HTML tant qu’il n’est pas téléchargé et exécuté. C’est pour cette raison que l’on place souvent les scripts juste avant la fermeture de l’élément body, afin que le navigateur puisse d’abord afficher le contenu de la page.
Les navigateurs modernes proposent également plusieurs attributs qui permettent de mieux contrôler ce chargement. L’attribut defer indique que le script peut être téléchargé pendant l’analyse du document mais qu’il ne sera exécuté qu’une fois le HTML entièrement parcouru. L’attribut async, de son côté, autorise un chargement et une exécution dès que le fichier est disponible, sans attendre l’ordre des autres scripts.
Ces mécanismes deviennent particulièrement importants lorsque plusieurs scripts doivent coopérer ou lorsqu’un script dépend d’un autre. Comprendre l’ordre de chargement permet d’éviter des erreurs difficiles à diagnostiquer et de mieux organiser l’exécution du code dans la page. Pour approfondir ces notions, on pourra également se référer à l’article : Mieux comprendre le chargement du Javascript dans une page web – Puce et Média.
Attendre que la page soit prête : le chargement du DOM
Dans la section précédente, nous avons évoqué la manière dont les scripts sont chargés dans une page HTML. Mais une autre question se pose rapidement : à quel moment le script peut‑il réellement agir sur la page ? En effet, lorsque le navigateur charge un document HTML, celui‑ci est analysé progressivement. Les éléments de la page apparaissent petit à petit dans la structure interne du navigateur que l’on appelle le DOM (Document Object Model). Tant que cette structure n’est pas prête, un script peut tenter d’accéder à des éléments qui n’existent pas encore.
Il est donc souvent nécessaire d’attendre que le document soit entièrement analysé avant d’exécuter certaines instructions JavaScript. Pour cela, le navigateur déclenche un événement spécifique lorsque le DOM est prêt : DOMContentLoaded. Cet événement permet de lancer du code uniquement lorsque la structure de la page est disponible et que JavaScript peut commencer à interagir avec les éléments du document.
document.addEventListener("DOMContentLoaded", () => {
console.log("La page est prête, le script peut s’exécuter.");
});Distinguer les approches sans s’y perdre
À ce stade du parcours, l’important n’est pas encore la structure complète d’une application JavaScript, mais simplement de comprendre qu’un script peut évoluer. On peut commencer par quelques lignes directement dans une page, puis déplacer progressivement le code dans des fichiers séparés, organiser les fonctions, et clarifier les responsabilités.
Autrement dit, le code JavaScript n’est pas figé. Dans un projet réel, on finit rapidement par créer plusieurs scripts, chacun dédié à une tâche précise : gestion des événements utilisateur, manipulation du DOM, communication avec un serveur, gestion du stockage local, ou encore validation de formulaires. Cette organisation peut se traduire par une arborescence de fichiers qui sépare clairement les responsabilités :
/js
events.js
dom.js
api.js
storage.js
forms.jsChaque fichier se concentre alors sur une fonction particulière de l’application. Mais ces scripts ne vivent pas isolément : ils peuvent avoir besoin de s’appeler ou de partager certaines informations. Dans ce cas, l’ordre dans lequel les scripts sont chargés dans la page devient important. Un script qui dépend d’un autre doit nécessairement être chargé après lui.
Comprendre cette logique de dépendance prépare naturellement la suite du parcours, où nous aborderons des méthodes plus structurées pour organiser le code et gérer ces relations entre fichiers. Les mécanismes plus avancés d’organisation, comme les modules ou la structuration d’un projet, seront abordés plus loin dans l’article lorsque les bases du langage et de l’environnement navigateur seront mieux installées.
Le langage JavaScript et son environnement
À ce stade, il est utile de clarifier une distinction qui prête souvent à confusion. Lorsque nous écrivons du JavaScript dans un navigateur, deux choses différentes coexistent.
- D’un côté se trouve le langage JavaScript lui‑même : ses variables, ses fonctions, ses objets, ses conditions, et toutes les règles qui constituent sa syntaxe.
- De l’autre côté se trouve l’environnement du navigateur. Celui‑ci met à disposition de nombreuses interfaces : le document HTML (le DOM), les événements utilisateur, le stockage local, les requêtes réseau, ou encore les éléments multimédias.
Autrement dit, JavaScript est le langage. Le navigateur fournit l’environnement avec lequel ce langage peut interagir. Cette distinction devient importante lorsque l’on commence à apprendre. Une partie de ce que nous découvrons appartient réellement au langage JavaScript. Une autre partie correspond aux interfaces que le navigateur expose pour permettre au script d’agir sur la page.

Comprendre cette différence aide à mieux structurer l’apprentissage : nous apprenons à la fois un langage, et la manière dont ce langage dialogue avec le navigateur.
Les événements utilisateur & système
Un site interactif repose presque toujours sur des événements. Un clic sur un bouton, un mouvement de souris, une saisie au clavier, le chargement d’une page ou encore la soumission d’un formulaire sont autant de situations que le navigateur peut signaler au script. Ces signaux constituent le point de départ de nombreuses interactions : afficher un message, modifier un contenu, ouvrir un panneau, valider une donnée ou déclencher une requête vers un serveur.
Les événements sont également très présents dans les formulaires : validation d’un champ, envoi d’un formulaire ou vérification d’une saisie. Nous reviendrons plus en détail sur ces mécanismes lorsque nous aborderons les échanges entre navigateur et serveur, en Part V.
JavaScript permet précisément d’écouter ces événements et d’y répondre. Le script s’enregistre auprès du navigateur pour être averti lorsqu’un événement particulier se produit, puis exécute une fonction qui contient le comportement attendu. Cette logique événementielle constitue l’un des fondements de l’interactivité dans les interfaces web. Pour écouter un événement, JavaScript utilise généralement la méthode addEventListener, voir EventTarget : méthode addEventListener() et surtout Les Événements en JavaScript : addEventListener. Celle‑ci associe un type d’événement à une fonction qui sera exécutée lorsque cet événement se produit.
const bouton = document.querySelector("button");
bouton.addEventListener("click", (event) => {
console.log("Le bouton a été cliqué");
});
Les événements suivent également un mécanisme appelé propagation. Lorsqu’un clic se produit sur un élément, l’événement ne concerne pas uniquement cet élément : il traverse la structure du document. Dans la phase la plus courante, appelée bubbling (propagation par bulle), l’événement remonte progressivement dans l’arbre du DOM, de l’élément cible vers ses éléments parents. Comprendre ce mécanisme devient important lorsque plusieurs éléments imbriqués peuvent réagir au même événement, car il permet de contrôler précisément quel comportement doit être exécuté.
Pour mettre en évidence la propagation des événements. Copiez le code fourni ci‑dessous…
<!DOCTYPE html>
<html>
<body>
<!-- Conteneur principal -->
<div id="container">
<!-- Formulaire intermédiaire -->
<form id="formulaire">
<!-- Élément déclencheur -->
<button id="bouton" type="button">
Cliquer ici
</button>
</form>
</div>
<script>
// Fonction utilitaire qui affiche le noeud qui reçoit l'événement
function observer(noeud, nom) {
// écoute du clic sur l'élément donné
noeud.addEventListener("click", function(event) {
// affiche l'élément sur lequel l'écouteur est placé
console.log("Listener sur :", nom);
// affiche l'élément réellement cliqué
console.log("event.target :", event.target.tagName);
console.log("---------------------");
});
}
// Récupération des différents noeuds du document
const html = document.documentElement; // élément <html>
const body = document.body; // élément <body>
const div = document.getElementById("container");
const form = document.getElementById("formulaire");
const button = document.getElementById("bouton");
// Ajout d'un écouteur sur chaque niveau du DOM
observer(html, "html");
observer(body, "body");
observer(div, "div");
observer(form, "form");
observer(button, "button");
</script>
</body>
</html>… Et collez‑le dans un environnement JavaScript simple. Pour cette illustration nous avons utilisé js.do. Prenez un instant pour analyser le script : les écouteurs d’événements sont placés successivement sur html, puis sur body, puis sur les éléments imbriqués jusqu’au button. Ils partent bien d’en haut pour descendre jusqu’au bouton.
observer(html, "html");
observer(body, "body");
observer(div, "div");
observer(form, "form");
observer(button, "button");Avant de cliquer, assurez‑vous que la console du navigateur soit bien ouverte, puis exécutez le script. Lorsque vous cliquez sur le bouton, vous verrez apparaître les messages dans la console : le bouton réagit d’abord, puis le form, puis le div, puis body, et enfin html. Peu importe l’ordre des scripts, l’événement part donc de l’élément cible et remonte progressivement dans la structure du document. Ce comportement correspond précisément au mécanisme de propagation appelé bubbling.


Premières notions d’organisation du code : portée et encapsulation
Très tôt, en explorant le JavaScript, nous rencontrons des notions comme les variables, leur portée, et la manière dont le code est organisé. Sans chercher à les maîtriser immédiatement, il est utile de comprendre qu’un code peut être global ou local, partagé avec toute la page ou au contraire limité à une partie précise du script.
Dans le navigateur, tout ce qui est déclaré au niveau le plus haut d’un script devient généralement accessible depuis l’objet global window. Cela signifie qu’une variable ou une fonction peut être utilisée partout… mais aussi qu’elle peut entrer en conflit avec d’autres scripts. Pour éviter cela, on cherche souvent à encapsuler certaines parties du code, c’est‑à‑dire à les isoler dans un espace où leurs variables ne seront pas exposées globalement. Un moyen simple d’y parvenir consiste à placer le code à l’intérieur d’une fonction exécutée lorsque la page est prête, par exemple dans le gestionnaire DOMContentLoaded.
Dans ce cas, les variables et fonctions définies dans ce bloc restent locales à cette fonction et ne sont pas directement attachées à l’objet window. Le code est ainsi mieux isolé et plus facile à organiser. Un exemple simple permet d’illustrer cette différence entre portée globale et portée locale :
// -----------------------------
// 1. Variable globale vs locale
// -----------------------------
let message = "variable globale"; // variable déclarée au niveau global
function demo() {
let local = "variable locale"; // variable visible uniquement dans cette fonction
console.log("Dans la fonction :");
console.log(message); // accessible car globale
console.log(local); // accessible car locale à la fonction
}
demo();
// La variable globale est également accessible depuis l'objet window
console.log("Depuis window :", window.message); // fonctionne
// La variable locale n'existe pas hors de la fonction
// console.log(window.local); // undefined
// -------------------------------------------------
// 2. Encapsulation avec DOMContentLoaded
// -------------------------------------------------
// Le code placé dans cet écouteur est exécuté
// lorsque la structure du document est prête
document.addEventListener("DOMContentLoaded", () => {
let messageLocal = "variable encapsulée"; // variable locale à ce bloc
function afficher() {
console.log("Depuis la fonction encapsulée :", messageLocal);
}
afficher(); // fonctionne à l'intérieur du bloc
// Même si la fonction est appelée ici,
// elle reste invisible à l'extérieur
});
// En dehors de ce bloc, rien n'est accessible
// console.log(window.messageLocal); // undefined
// console.log(window.afficher); // undefined
// L'encapsulation protège donc les variables
// et évite de polluer l'espace global windowManipuler le document : le DOM
Nous avons déjà croisé la notion de DOM dans la part II de cette série. Le DOM représente la page telle que le navigateur la reconstruit en mémoire après avoir analysé le document HTML. Chaque élément devient alors un nœud que JavaScript peut parcourir, lire et modifier. Grâce à cette représentation, un script peut accéder aux éléments de la page, changer un texte, ajouter un élément, supprimer une section ou modifier un attribut. C’est ce mécanisme qui permet de transformer un document HTML statique en interface dynamique. Un exemple simple consiste à générer dynamiquement une liste HTML à partir d’un tableau JavaScript :
<ul id="liste"></ul>
<script>
// Tableau de données côté JavaScript
const fruits = ["Pommes", "Poires", "Cerises", "Abricots"];
// Sélection de l'élément <ul> dans la page
const liste = document.getElementById("liste");
// Parcours du tableau et création des éléments <li>
fruits.forEach((fruit) => {
const item = document.createElement("li"); // création d'un élément de liste
item.textContent = fruit; // insertion du texte
liste.appendChild(item); // ajout dans la liste HTML
});
</script>
Dans cet exemple, les données existent d’abord sous forme de tableau JavaScript. Le script crée ensuite les éléments HTML nécessaires et les insère dans le document. C’est un cas très courant : une page peut recevoir des données, puis construire ou modifier son interface en fonction de ces informations.
Le DOM permet également d’associer des informations aux éléments de la page. Les attributs personnalisés, accessibles via la propriété dataset, servent souvent à stocker des données directement dans le HTML afin que JavaScript puisse les exploiter ensuite pour piloter un comportement ou une interaction. Un exemple courant consiste à placer des informations directement dans les attributs data-* du HTML, puis à les lire côté JavaScript :
<ul id="produits">
<li data-id="101" data-prix="3.50">Pommes</li>
<li data-id="102" data-prix="2.90">Poires</li>
<li data-id="103" data-prix="4.20">Cerises</li>
</ul>
<script>
// sélection de tous les éléments de la liste
const produits = document.querySelectorAll("#produits li");
produits.forEach((item) => {
// accès aux attributs data-* via dataset
const id = item.dataset.id;
const prix = item.dataset.prix;
console.log("Produit", id, "prix :", prix);
});
</script>
Dans cet exemple, certaines informations (identifiant, prix) sont directement stockées dans le HTML. JavaScript peut ensuite les récupérer grâce à la propriété dataset. Cette technique est très utilisée pour associer des données à un élément de l’interface sans devoir les recalculer ou interroger immédiatement un serveur.
Mais manipuler le DOM ne suffit pas à rendre une page interactive. L’interactivité naît généralement d’un événement. Un clic, un déplacement de souris, une saisie au clavier ou même le chargement d’une page peuvent déclencher une action. JavaScript agit alors comme un intermédiaire entre l’utilisateur et la page : il écoute ces événements, puis déclenche le code approprié. Un bouton peut afficher un message, un formulaire peut vérifier une saisie, ou un contenu peut se mettre à jour sans recharger la page.
C’est cette combinaison entre événements et manipulation du DOM qui constitue le cœur des interactions dans une page web moderne. Pour approfondir cette approche, la documentation MDN propose une introduction détaillée au DOM scripting, Manipuler des documents. On peut également mentionner deux ouvrages souvent cités dans ce domaine : DOM Enlightenment de Cody Lindley (O’Reilly), qui propose une exploration très claire du fonctionnement interne du DOM, ainsi que DOM Scripting de Jeremy Keith, publié chez Friends of ED. Bien que ce dernier date d’une vingtaine d’années, il reste une lecture marquante pour comprendre la logique qui relie HTML, CSS et JavaScript dans la manipulation du document.
Les APIs natives du navigateur
Lorsque nous écrivons du JavaScript dans un navigateur, nous ne manipulons pas uniquement le langage lui‑même. Le navigateur met également à disposition de nombreuses interfaces, appelées APIs (Application Programming Interfaces). Elles permettent au script d’interagir avec différentes capacités du navigateur : le stockage local, les communications réseau, le multimédia, ou encore certaines fonctions liées au système de l’utilisateur. Ces APIs font partie intégrante du navigateur. Autrement dit, elles sont déjà présentes et utilisables sans installer de bibliothèque externe.
Au moment de l’arrivée de HTML5, certaines d’entre elles ont marqué une rupture importante. Les APIs associées aux éléments audio et video ont par exemple profondément changé la manière d’intégrer du contenu multimédia dans les pages web . Avant leur apparition, la lecture de vidéos ou de sons reposait presque toujours sur des technologies externes comme Flash ou d’autres plugins propriétaires. L’intégration native du multimédia dans le navigateur a donc constitué une évolution majeure Vidéo – Puce et Média.
Mais ces deux exemples ne représentent qu’une petite partie de l’écosystème qui s’est développé autour du navigateur. Avec HTML5 et l’évolution des standards du web, de nombreuses APIs sont venues élargir les possibilités offertes aux applications web. Certaines sont aujourd’hui très courantes, comme Web Storage (avec localStorage et sessionStorage) ou IndexedDB, qui permettent de stocker des données directement dans le navigateur. D’autres ouvrent des usages plus spécialisés : Canvas API pour dessiner et produire des graphiques, Web Workers pour exécuter du code dans un thread séparé, WebSockets pour les communications temps réel, Geolocation API pour accéder à la position d’un utilisateur, Drag and Drop API pour manipuler des éléments à l’écran, WebRTC pour les communications audio et vidéo entre navigateurs, ou encore FileReader API pour lire des fichiers locaux.
Pour prendre conscience de l’étendue de ces interfaces, il peut être intéressant de consulter une cartographie globale de l’écosystème HTML5 sur HTML5index.org, ou sur Web APIs chez MDN. L’ensemble de ces interfaces illustre une évolution profonde du navigateur. Ce dernier n’est plus seulement un outil d’affichage de documents : il est devenu une véritable plateforme d’exécution capable d’héberger des applications complètes.
Dans la pratique, il est souvent utile de vérifier qu’une API est bien disponible dans le navigateur avant de l’utiliser. Par exemple :
if ('localStorage' in window) {
console.log("localStorage est disponible");
}Cette cartographie rappelle un point essentiel : JavaScript n’agit jamais seul. Il dialogue en permanence avec les interfaces fournies par le navigateur, qui constituent la véritable boîte à outils permettant de construire des applications web modernes. Pour approfondir cette notion d’APIs côté navigateur, la documentation MDN propose également une introduction claire aux Client‑side APIs.
Stockage côté navigateur et échanges de données
Jusqu’ici, nous avons surtout manipulé des variables dont la durée de vie se limite à l’exécution du script. Mais une application web a souvent besoin de conserver certaines informations dans le navigateur : préférences d’un utilisateur, état d’une interface, données temporaires, etc. Le navigateur met pour cela à disposition plusieurs mécanismes de stockage local :
localStorage, qui conserve les données de manière persistantesessionStorage, qui garde les données uniquement pendant la session du navigateurIndexedDB, qui permet de gérer des structures de données plus complexes
Ces mécanismes permettent donc à une application de mémoriser certaines informations directement côté client, sans communication immédiate avec un serveur. Pour approfondir ces sujets, vous pouvez consulter les articles suivants :
- Stockage local en JavaScript : bien utiliser localStorage et sessionStorage,
- Comprendre IndexedDB : une base de données locale en JavaScript,
- Explorer et modifier les données dans IndexedDB : curseurs, accès directs et transactions
- et IndexedDB : relations, structures avancées et bonnes pratiques.
Cependant, une application web ne se limite pas aux données qu’elle possède déjà. Très vite, elle doit aussi échanger des informations avec un serveur : récupérer du contenu, envoyer des formulaires, synchroniser des données ou interagir avec d’autres services.
Le rôle du JSON dans ces échanges
Pour que ces échanges soient possibles, il faut un format capable d’être compris par différents systèmes. C’est précisément le rôle de JSON. JSON (JavaScript Object Notation) est un format de données simple et lisible qui permet de représenter des informations sous forme de paires clé–valeur et de listes. Il est compris naturellement par JavaScript mais aussi par la plupart des langages utilisés côté serveur. Un exemple JSON très simple peut ressembler à ceci :
{
"titre": "Parcours JavaScript",
"auteur": "Puce & Média",
"chapitres": ["DOM", "événements", "APIs"]
}Dans JavaScript, ces données peuvent ensuite être manipulées comme un objet :
const data = {
titre: "Parcours JavaScript",
auteur: "Puce & Média",
chapitres: ["DOM", "événements", "APIs"]
};
console.log(data.titre);Comprendre JSON revient donc à comprendre comment les données circulent entre différentes parties d’une application : le navigateur, le serveur, ou parfois d’autres services externes. La documentation MDN propose également une introduction très claire sur comment Manipuler des données JSON.
Quelques outils pour explorer le JSON
Lorsque l’on commence à manipuler des structures JSON, certains outils peuvent être utiles pour visualiser ou valider les données :
- un éditeur interactif : https://jsoneditoronline.org/
- un validateur et formateur : https://jsonformatter.curiousconcept.com/
- un outil polyvalent d’exploration : https://jsonlab.xyz/
Ces outils permettent notamment de vérifier la structure d’un document JSON, d’explorer des objets complexes ou de reformater les données pour les rendre plus lisibles.
Les requêtes réseau : XMLHttpRequest et Fetch
Une fois les données structurées, encore faut‑il pouvoir les échanger entre le navigateur et un serveur. C’est ce que permettent les mécanismes de requêtes réseau en JavaScript. Historiquement, cette possibilité s’est popularisée avec AJAX, terme introduit en 2005 par Jesse James Garrett. L’idée était simple mais décisive : permettre à une page web d’envoyer ou de recevoir des données sans recharger complètement la page. Pendant longtemps, cet échange s’est appuyé sur l’objet XMLHttpRequest, qui permet d’envoyer une requête HTTP et de récupérer une réponse du serveur.
const req = new XMLHttpRequest();
req.open("GET", "/data.json");
req.onload = () => console.log(req.responseText);
req.send();Avec le temps, JavaScript a évolué et propose aujourd’hui des interfaces plus modernes. L’API fetch simplifie par exemple l’écriture des requêtes asynchrones et la manipulation des données JSON.
fetch("/data.json")
.then(response => response.json())
.then(data => console.log(data));Ces mécanismes ont profondément transformé les applications web. Une page n’est plus seulement un document chargé une fois : elle peut désormais dialoguer en permanence avec des sources de données, récupérer des informations, envoyer des actions utilisateur et mettre à jour l’interface sans rechargement complet. Pour approfondir ces mécanismes, on pourra consulter les ressources suivantes :
- Comprendre XMLHttpRequest 2 : un article qui présente l’évolution de l’objet
XMLHttpRequestet les améliorations introduites par sa seconde version, notamment la gestion de fichiers, de flux de données et une meilleure gestion des erreurs dans les échanges avec un serveur. - L’évolution des requêtes HTTP et des opérations asynchrones : une mise en perspective de la manière dont les requêtes JavaScript ont évolué, depuis
XMLHttpRequestjusqu’aux Promises et à l’APIfetch, afin de rendre les échanges réseau plus lisibles et plus structurés. - Retour historique sur vingt ans d’AJAX : un regard historique sur la naissance d’AJAX, terme popularisé en 2005 par Jesse James Garrett pour décrire une approche permettant aux pages web d’échanger des données avec un serveur sans recharger toute la page.
Organiser le code avec les modules JavaScript
Lorsque les projets deviennent plus importants, placer tout le code dans un seul fichier devient rapidement difficile à maintenir. Les modules JavaScript permettent de découper l’application en plusieurs fichiers spécialisés. Chaque fichier peut exposer certaines fonctions ou variables, et importer celles dont il a besoin depuis d’autres modules. Cette organisation permet de répartir clairement les responsabilités dans le code. Dans un projet simple, on peut par exemple structurer les fichiers ainsi :
project
│
├─ modules.html
└─ js
├─ utils.js
└─ app.jsChaque fichier possède alors un rôle précis. Cette organisation rend le projet plus lisible et plus facile à maintenir.
Créer un premier module
Un module peut exporter certaines fonctions afin qu’elles soient utilisées ailleurs dans l’application. Ici, le fichier utils.js expose une fonction formatDate. Le mot clé export indique que cette fonction peut être utilisée par d’autres modules.
// utils.js
export function formatDate(date) {
return new Date(date).toLocaleDateString();
}Importer une fonction depuis un autre module
Un second fichier peut maintenant importer cette fonction pour l’utiliser. L’instruction import indique au navigateur qu’il doit charger le fichier utils.js afin d’utiliser la fonction exportée.
// app.js
import { formatDate } from './utils.js';
console.log(formatDate('2024-01-10'));Charger le module dans une page HTML
Pour que le navigateur comprenne que le script utilise le système de modules, il faut charger le script avec l’attribut type="module". Le navigateur interprète alors le contenu du bloc comme un module JavaScript. Dans cet exemple, la page importe directement la fonction formatDate depuis le fichier utils.js. Cette mécanique crée ce que l’on appelle une dépendance entre la page et le module : le navigateur doit charger utils.js pour pouvoir exécuter le code présent dans la page.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Modules JavaScript</title>
</head>
<body>
<p>Test de chargement d'un module JavaScript</p>
<script type="module">
import { formatDate } from './js/utils.js';
console.log(formatDate('2024-01-10'));
</script>
</body>
</html>Premier test : ouverture directe du fichier
Si l’on ouvre simplement le fichier modules.html depuis le disque avec une URL de type file://, le navigateur bloque le chargement du module. Cette erreur provient d’une restriction de sécurité du navigateur. Les modules JavaScript sont soumis à des règles plus strictes que les scripts classiques, et les dépendances ne peuvent pas être chargées librement depuis le système de fichiers.

Solution : utiliser un petit serveur local
Pour vérifier le fonctionnement des modules dans ce chapitre, nous lançons simplement la page depuis un petit serveur local. L’objectif ici n’est pas d’étudier le fonctionnement du serveur lui-même, mais uniquement de constater que, servie en HTTP, la page peut charger le module sans erreur. La page est alors ouverte via une adresse de type :
http://localhost:3000/modules.html
Le navigateur accepte alors le chargement du module utils.js et le script s’exécute comme attendu. Nous reviendrons plus en détail sur la mise en place d’un serveur local et sur les échanges client‑serveur dans l’article suivant de la série (Part V).
Ce qu’il faut retenir
Les modules JavaScript apportent plusieurs bénéfices importants :
- le code est mieux organisé
- les responsabilités sont réparties entre plusieurs fichiers
- les variables globales sont limitées
- les dépendances deviennent explicites
Mais ils introduisent aussi quelques contraintes : les fichiers doivent être chargés depuis un serveur HTTP, même en phase de développement. Dans les projets plus importants, ces modules sont souvent combinés avec des outils capables de regrouper et optimiser les fichiers JavaScript. Ces outils appartiennent à ce que l’on appelle l’outillage moderne du développement JavaScript.
Les modules constituent ainsi une étape importante dans l’évolution d’un projet : ils permettent de passer d’un simple script isolé à une organisation structurée et maintenable du code, pour aller plus loin voir Les modules JavaScript sur MDN.
Bibliothèques et frameworks JavaScript
Une fois les bases de JavaScript et l’organisation du code avec les modules comprises, il devient plus facile de comprendre ce que l’on appelle les bibliothèques et les frameworks. Ces outils font partie de l’univers JavaScript, mais ils n’en remplacent pas les fondations. Les évoquer ici permet surtout de comprendre leur place et leur rôle, sans encore dépendre de ces outils.
Une bibliothèque est généralement un ensemble de fonctions ou d’outils que l’on peut utiliser lorsque l’on en a besoin. Elle vient compléter le langage et simplifier certaines opérations. Par exemple, jQuery a longtemps été utilisé pour faciliter la manipulation du DOM et la gestion des événements. D’autres bibliothèques comme Lodash proposent des fonctions utilitaires pour manipuler des tableaux ou des objets.
souvent une manière d’organiser le projet, de gérer l’interface et de structurer les interactions. Des frameworks comme React, Vue ou Angular permettent par exemple de construire des interfaces complexes en organisant l’application autour de composants. React est particulièrement apprécié pour sa gestion efficace des interfaces dynamiques et son approche basée sur des composants réutilisables. Vue est souvent reconnu pour sa simplicité de prise en main et sa capacité à s’intégrer progressivement dans un projet existant. Angular, plus structuré, propose un cadre complet pour développer des applications de grande ampleur avec une organisation très encadrée du code.
La différence est souvent résumée de manière simple. Avec une bibliothèque, le développeur garde la maîtrise du flux du programme et appelle les fonctions dont il a besoin. Avec un framework, le framework structure l’application et appelle le code du développeur au bon moment.
Les utiliser simplement dans une page HTML
Même si ces outils peuvent être installés dans un projet via NPM ou un bundler, il est possible de comprendre leur principe en les insérant directement dans une page HTML. Cette approche permet simplement de comprendre leur fonctionnement sans modifier l’organisation du projet. Par exemple, une bibliothèque comme jQuery peut être chargée directement dans une page :
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
$(document).ready(function () {
console.log("jQuery est chargé et prêt à être utilisé");
});
</script>Pour observer le principe d’un framework sans installer d’outillage particulier, nous pouvons charger Vue.js directement dans une page HTML via un CDN.
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<div id="app">{{ message }}</div>
<script>
const { createApp } = Vue;
createApp({
data() {
return {
message: "Bonjour Vue"
};
}
}).mount("#app");
</script>Ces exemples ne cherchent pas à construire une application complète. Ils permettent simplement de voir comment ces outils s’intègrent dans une page web. Nous avons d’ailleurs consacré une série d’articles à Vue.js https://www.puce-et-media.com/tag/vue-js/, afin d’explorer progressivement la manière dont ce framework permet de structurer une interface autour de composants, de données réactives et de mécanismes d’interaction. Cette série peut être consultée ici :
Le rôle des CDN
Dans les exemples précédents, les fichiers JavaScript ne sont pas stockés dans le projet. Ils sont chargés depuis des serveurs externes appelés CDN. Un CDN, Content Delivery Network, est un réseau de serveurs répartis dans différentes régions du monde. Son rôle consiste à distribuer des fichiers de manière rapide et fiable. Lorsqu’un navigateur demande une bibliothèque hébergée sur un CDN, celle ci est généralement téléchargée depuis un serveur proche géographiquement de l’utilisateur. Plusieurs CDN sont largement utilisés dans l’écosystème web :
Ces services permettent de charger rapidement des bibliothèques très répandues comme jQuery, Vue, React ou Bootstrap.
Dans un projet réel, les bibliothèques sont souvent installées localement avec NPM et intégrées dans le processus de construction du projet. Mais l’utilisation d’un CDN reste très pratique pour expérimenter une bibliothèque, tester un exemple ou comprendre rapidement son fonctionnement. Découvrir ces outils à ce stade permet de les aborder avec plus de recul. Ils deviennent alors des aides possibles pour organiser un projet, et non des solutions magiques dont on dépend sans comprendre leur fonctionnement.
L’objectif reste donc le même : comprendre progressivement les mécanismes qui permettent à JavaScript d’enrichir et de structurer l’interactivité, avant d’explorer plus en détail les outils qui se construisent autour de lui.
Node.js et NPM dans l’écosystème JavaScript
En explorant JavaScript, nous rencontrons rapidement Node.js. Contrairement au JavaScript exécuté dans le navigateur, Node.js permet d’exécuter JavaScript en dehors du navigateur, directement sur le système ou côté serveur. Cela ouvre une première perspective : utiliser JavaScript pour construire des applications serveur, des scripts d’automatisation ou même des outils en ligne de commande.
Mais Node.js joue également un autre rôle très important dans l’écosystème du développement web et ouvre plusieurs perspectives : automatiser certaines tâches, créer des outils de développement ou préparer les ressources d’un projet web.
Dans le cadre de ce parcours, il n’est pas encore nécessaire d’entrer dans les détails de l’exécution côté serveur. Nous y reviendrons dans la Part V, consacrée aux relations entre le navigateur et le serveur. Pour l’instant, retenons surtout que Node.js est devenu un outil central dans l’écosystème JavaScript. Pour découvrir concrètement cet environnement, vous pouvez consulter l’article : Prendre en main Node.js.
Le rôle de NPM
Autour de Node.js s’est développé un gestionnaire de paquets appelé NPM (Node Package Manager). Son principe est simple : il permet d’installer et de gérer des bibliothèques ou des outils qui peuvent être utilisés dans un projet JavaScript. Par exemple:
npm install nom-du-paquetUn projet JavaScript peut ainsi déclarer ses dépendances dans un fichier package.json, que NPM utilisera pour installer automatiquement les bibliothèques nécessaires.
{
"name": "mon-projet",
"dependencies": {
"dayjs": "^1.11.10"
}
}Dans cet exemple, nous installons la bibliothèque dayjs, un petit outil très simple qui permet de manipuler et formater des dates en JavaScript. Une fois la dépendance installée avec NPM, elle peut être utilisée directement dans le code. Pour tester cet exemple, on peut suivre une séquence très simple dans un dossier vide :
npm init -y
npm install dayjsCes commandes créent le fichier package.json puis installent la bibliothèque dans le dossier node_modules. Il suffit ensuite de créer un petit fichier JavaScript, par exemple test-date.js :
// test-date.js
import dayjs from 'dayjs';
const aujourdHui = dayjs().format('YYYY-MM-DD');
console.log(aujourdHui);Puis de l’exécuter avec Node :
node test-date.jsLe script affiche alors la date du jour formatée dans la console.
Pour apprendre à rechercher et installer des bibliothèques avec NPM, vous pouvez également consulter : Trouver et installer des packages sous Node.js.
Un outil d’outillage pour les projets JavaScript
Dans la pratique, NPM sert autant à installer des bibliothèques JavaScript comme celle‑ci qu’à utiliser des outils de production qui aident à préparer le code avant sa mise en ligne. Parmi ces outils, on trouve par exemple :
- des outils de minification comme UglifyJS ou Terser, qui réduisent la taille des fichiers JavaScript
- des outils de bundling comme Webpack, Rollup ou Vite, capables de regrouper plusieurs modules en un seul fichier optimisé
- des outils de transpilation comme Babel, qui permettent d’utiliser des syntaxes modernes tout en restant compatibles avec différents navigateurs
- des outils d’automatisation comme Gulp ou npm scripts, qui facilitent certaines tâches répétitives
Grâce à cet écosystème, JavaScript n’est plus seulement un langage exécuté dans une page web : il devient aussi un environnement complet de développement, capable d’accompagner la création, l’organisation et l’optimisation d’un projet.
Même si notre apprentissage commence dans le navigateur, il est utile de savoir que cet univers existe. Une grande partie des outils modernes du développement web s’appuie aujourd’hui sur Node.js et sur NPM.
L’outillage moderne : bundlers, transpilation et organisation
Avant d’entrer dans le détail, précisons un point important. Les outils présentés dans ce chapitre dépassent en partie le cadre du présent article. Notre objectif ici n’est pas d’apprendre à les utiliser, mais plutôt de situer quelques notions que l’on rencontre souvent dans l’écosystème JavaScript. Les termes comme bundler, transpilation ou TypeScript apparaissent fréquemment dans la documentation, les tutoriels ou les discussions entre développeurs. Il est donc utile de comprendre à quoi ils correspondent et quel rôle ils jouent dans l’organisation d’un projet JavaScript moderne.
Lorsque nous découvrons JavaScript, il est fréquent d’écrire quelques scripts directement dans une page ou dans un fichier unique. Cette approche fonctionne très bien pour apprendre et pour des projets simples. Mais à mesure que les applications deviennent plus importantes, le code se répartit dans plusieurs fichiers, utilise des modules, et dépend parfois de bibliothèques externes.
C’est dans ce contexte qu’apparaissent ce que l’on appelle les outils de production du développement JavaScript. Leur objectif n’est pas de remplacer le langage, mais d’aider à organiser, transformer et optimiser le code avant qu’il ne soit envoyé au navigateur.
L’un des rôles les plus connus est celui des bundlers. Un bundler analyse les différents modules d’un projet et peut regrouper plusieurs fichiers JavaScript en un seul fichier optimisé. Cela permet de simplifier le chargement côté navigateur et d’améliorer les performances. Parmi les bundlers les plus connus on peut citer Webpack, Rollup, Vite ou encore esbuild, chacun proposant une manière différente d’organiser et d’optimiser le code.
Un autre rôle important est celui de la transpilation. Certains développeurs utilisent des syntaxes modernes ou des extensions du langage. La transpilation consiste alors à transformer ce code en JavaScript standard compatible avec différents navigateurs. Des outils comme Babel ou SWC sont souvent utilisés pour effectuer ce travail de conversion. Prenons par exemple un code utilisant une syntaxe moderne :
const addition = (a, b) => a + b;Un outil de transpilation peut convertir cette écriture en une version plus ancienne mais largement compatible :
var addition = function(a, b) {
return a + b;
};Ces outils ne sont pas indispensables pour apprendre JavaScript, mais ils deviennent très courants dans les projets professionnels. Ils permettent d’automatiser certaines tâches répétitives, d’organiser les modules d’un projet et de produire un code final plus compact et plus performant.
À mesure que l’écosystème JavaScript s’est développé, d’autres outils sont venus compléter cet environnement. Certains ajoutent des fonctionnalités supplémentaires, comme TypeScript, qui introduit un système de typage pour mieux structurer les applications. D’autres proposent des moteurs de templates ou des syntaxes alternatives, comme Mustache ou Handlebars, qui facilitent la génération de contenu HTML.
Il est important de comprendre que ces outils ne remplacent pas JavaScript : ils produisent généralement du JavaScript standard qui sera exécuté dans le navigateur. Ils constituent simplement une étape supplémentaire dans la préparation d’un projet lorsque celui-ci grandit et se complexifie.
Aller plus loin : du navigateur vers le serveur
Jusqu’ici, tout se déroule dans le navigateur. JavaScript écoute des événements, modifie le document, stocke certaines informations localement et peut charger des données à distance. Mais un projet web réel ne se limite pas à l’interface visible dans la page. Derrière l’écran intervient un serveur capable de fournir des données, d’enregistrer des informations, de gérer des utilisateurs ou d’orchestrer des traitements plus complexes.
La prochaine étape du parcours consiste donc à comprendre comment le navigateur et le serveur dialoguent réellement. Nous verrons d’abord ce qu’est concrètement un serveur, quelles formes il peut prendre et quels rôles il peut assurer dans une application web. Nous observerons ensuite comment une requête part du navigateur, comment un serveur y répond et comment les données circulent entre ces deux mondes.
Cette relation entre client et serveur constitue l’un des fondements du web moderne. Elle ouvre naturellement la suite du parcours, consacrée à la relation client‑serveur, au déploiement et aux bases de l’infrastructure web.
