Qu’est-ce que JavaScript ?
JavaScript est un langage de programmation qui s’exécute à l’intérieur d’un environnement hôte et vous permet de contrôler ce qui se passe sur une page. HTML fournit la structure, CSS s’occupe de la présentation, et JavaScript apporte le comportement. Lorsqu’un menu s’ouvre, qu’un formulaire est validé, qu’une page charge de nouvelles données sans se rafraîchir ou qu’un jeu répond à votre clavier, c’est JavaScript qui fait le travail.
C’est un langage de haut niveau, à typage dynamique et multi-paradigme. Pour simplifier : vous ne gérez pas la mémoire manuellement, vous ne déclarez pas les types à l’avance, et vous pouvez écrire dans un style orienté objet, fonctionnel ou impératif selon les besoins du problème.
Le langage a été créé en 1995 pour une seule mission — rendre les pages web un peu interactives — et il a totalement dépassé ce cadre. Aujourd’hui, cette même syntaxe fait tourner des serveurs, des applications mobiles, des outils en CLI et des applications de bureau. L’apprendre est l’un des investissements les plus rentables que vous puissiez faire dans le développement web.
Où s’exécute JavaScript
JavaScript est le langage. Un runtime est l’environnement qui l’exécute. Le runtime le plus familier est le navigateur, mais il est loin d’être le seul.
- Les navigateurs intègrent un moteur JavaScript (V8 dans Chrome, SpiderMonkey dans Firefox, JavaScriptCore dans Safari) ainsi que des API hôtes comme le DOM,
fetch, les timers et le stockage. - Node.js, Deno et Bun exécutent JavaScript sur le serveur avec des API pour les fichiers, les réseaux et les processus.
- Les runtimes embarqués exécutent JavaScript dans des applications mobiles, des applications de bureau, des bases de données et même des microcontrôleurs.
Le langage lui-même est standardisé sous le nom d’ECMAScript. Le DOM, fetch et console ne font pas partie du langage — ce sont des API fournies par le runtime. Garder cette distinction à l’esprit permet de comprendre pourquoi un même code fonctionne dans un environnement et pas dans un autre.
Variables : let, const et var
Une variable est une référence nommée vers une valeur. Le JavaScript moderne propose trois façons d’en créer, mais vous n’en avez besoin que de deux.
// app.js
const name = "Ada"; // cannot be reassigned
let score = 0; // can be reassigned
score = score + 10;
// var is the legacy form — avoid it in new code
var old = true;
Utilisez const par défaut. Cela ne rend pas la valeur immuable — vous pouvez toujours modifier le contenu d’un objet ou d’un tableau const — cela empêche simplement de réassigner le nom à une valeur différente. Utilisez let lorsqu’une valeur change réellement, comme pour un compteur ou un accumulateur. Ne recourez à var que lors de la lecture de vieux codes.
Types de données
JavaScript dispose d’un petit ensemble de types primitifs ainsi que d’objets.
| Type | Exemple | Notes |
|---|---|---|
| string | "hello" |
Texte, guillemets simples, doubles ou backticks |
| number | 42, 3.14 |
Un seul type numérique pour les entiers et les flottants |
| bigint | 9007199254740993n |
Entiers de taille arbitraire |
| boolean | true, false |
Valeurs logiques |
| undefined | undefined |
Une valeur déclarée mais non assignée |
| null | null |
Une absence intentionnelle de valeur |
| symbol | Symbol("id") |
Identifiants uniques |
| object | { name: "Ada" } |
Collections, fonctions, tableaux — tout le reste |
L’opérateur typeof vous indique avec quoi vous travaillez. Attention à deux particularités célèbres : typeof null est "object" (un bug historique conservé pour la compatibilité) et typeof une fonction est "function" alors que les fonctions sont des objets.
Fonctions
Les fonctions sont des blocs de logique réutilisables et, en JavaScript, elles sont considérées comme des valeurs. Vous pouvez les stocker dans des variables, les passer en arguments et les retourner depuis d’autres fonctions.
// greet.js
function greet(name) {
return `Hello, ${name}!`;
}
const add = (a, b) => a + b;
const shout = (text) => text.toUpperCase();
La forme de déclaration function est hoistée, elle peut donc être appelée avant son apparition dans le code. Les fonctions fléchées (=>) sont plus courtes, n’ont pas leur propre this et sont idéales pour les callbacks. Lorsqu’une fonction ne contient qu’une seule expression, le corps et le return peuvent être omis.
Les fonctions peuvent également avoir des paramètres par défaut et accepter un nombre variable d’arguments grâce à la syntaxe rest :
// math.js
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
function greet(name = "friend") {
return `Hi, ${name}`;
}
sum(1, 2, 3); // 6
Objets et tableaux
Les objets stockent des valeurs nommées ; les tableaux stockent des valeurs ordonnées. Ensemble, ils permettent de modéliser presque toutes les données que vous manipulerez.
// data.js
const user = {
name: "Ada",
age: 36,
admin: true,
};
const skills = ["HTML", "CSS", "JavaScript"];
user.name; // "Ada"
skills.length; // 3
skills[0]; // "HTML"
Vous pouvez déstructurer les deux pour extraire des valeurs proprement, et utiliser l’opérateur spread pour en créer des copies :
// destructure.js
const { name, age } = user;
const [first, ...rest] = skills;
const updated = { ...user, age: 37 };
const moreSkills = [...skills, "TypeScript"];
Les objets et les tableaux sont des types de référence. Assigner l’un d’eux à une autre variable copie la référence, et non le contenu ; ainsi, toute mutation via l’un ou l’autre nom modifie la même valeur sous-jacente. Le spread permet de créer une copie superficielle (shallow copy) lorsque vous avez besoin d’indépendance.
Flux de contrôle
Les conditionnels et les boucles dirigent le flux de votre programme.
// logic.js
if (score >= 90) {
grade = "A";
} else if (score >= 80) {
grade = "B";
} else {
grade = "C";
}
for (const skill of skills) {
console.log(skill);
}
Privilégiez for...of pour les tableaux et for...in uniquement pour énumérer les clés d’un objet. L’opérateur ternaire condition ? a : b est une expression compacte lorsque vous avez besoin d’une valeur plutôt que d’une branche avec des effets de bord. L’opérateur de coalescence nulle ?? et le chaînage optionnel ?. rendent le code défensif plus lisible :
// safe.js
const city = user.address?.city ?? "Unknown";
Portée et fermetures (closures)
La portée (scope) définit l’endroit où une variable est visible. Un bloc { } crée une portée pour let et const. Une fonction crée une portée pour tout ce qu’elle contient. Les fermetures (closures) en sont la conséquence : une fonction interne conserve l’accès aux variables de la fonction externe, même après que cette dernière a retourné une valeur.
// counter.js
function createCounter() {
let count = 0;
return function () {
count += 1;
return count;
};
}
const next = createCounter();
next(); // 1
next(); // 2
La fonction retournée « enferme » count, le maintenant ainsi actif et privé. Les closures sont au cœur des gestionnaires d’événements, de la mémoïsation, du currying et des patterns de modules. C’est l’un des concepts les plus importants du langage, et une fois qu’on le maîtrise, une grande partie de JavaScript devient limpide.
L’event loop : premier aperçu
JavaScript exécute votre code sur un seul thread — il ne peut donc faire qu’une seule chose à la fois. Pourtant, il ne se fige jamais en attendant une requête réseau. L’astuce réside dans l’event loop.
Le code synchrone s’exécute immédiatement sur la call stack. Lorsque vous planifiez une opération asynchrone, comme un timer ou un fetch, le runtime s’en charge et continue son exécution. Une fois l’opération terminée, son callback est mis en file d’attente. L’event loop ne récupère le travail en attente que lorsque la stack est vide.
// loop.js
console.log("1");
setTimeout(() => console.log("2"), 0);
console.log("3");
// Output: 1, 3, 2
Même avec un délai de zéro milliseconde, le callback attend que le code synchrone actuel soit terminé. Cet ordonnancement est le fondement des promesses et de async/await, abordés en détail dans le guide JavaScript asynchrone.
Comment ajouter du JavaScript à une page
Vous liez du JavaScript au HTML à l’aide d’un élément <script>. Placez-le à la fin du body, ou utilisez l’attribut defer pour que le HTML soit analysé avant l’exécution de votre code.
<!-- index.html -->
<body>
<h1>Hello</h1>
<script src="app.js" defer></script>
</body>
Les scripts inline fonctionnent également, mais les fichiers externes sont miscibles en cache, réutilisables et plus faciles à déboguer. Utilisez type="module" pour charger des ES modules avec import et export.
Erreurs courantes
- Utiliser
varet être surpris par le hoisting ou la portée des fonctions. - Comparer avec
==et déclencher une coercition de type inattendue. Utilisez===. - Muter un objet ou un tableau en supposant qu’une copie a été créée.
- Oublier que
thisdépend de la manière dont une fonction est appelée, et non de l’endroit où elle est définie. - Traiter
nulletundefinedcomme interchangeables sans raison particulière. - Se tourner vers un framework avant de maîtriser les fonctions et les objets de base.
Bonnes pratiques
- Privilégiez
const, puislet, et évitezvar. - Utilisez toujours
===et!==, sauf si vous souhaitez explicitement une coercition. - Gardez vos fonctions courtes et concentrées sur une seule tâche.
- Nommez vos éléments selon leur signification, et non selon leur type.
- Utilisez l’optional chaining et le nullish coalescing pour un accès sécurisé.
- Apprenez le langage avant le framework. Les fondamentaux sont plus durables que les outils.
Quelle est la suite ?
Vous maîtrisez désormais le modèle conceptuel : valeurs, variables, fonctions, objets, portée (scope) et la boucle d’événements (event loop). À partir d’ici, les étapes logiques suivantes sont le DOM pour interagir avec les pages, les fonctionnalités ES6+ pour une syntaxe moderne, et le JavaScript asynchrone pour les promesses et async/await. Choisissez-en un, créez un petit projet et laissez la pratique porter ses fruits.