Apprendre JavaScript de zéro jusqu'au niveau expert : syntaxe moderne, DOM, asynchrone et event loop, modules, prototypes, métaprogrammation, performance et mémoire.
En JavaScript, les fonctions sont des valeurs. On les stocke dans des variables, on les passe en argument, on les renvoie. Toute l'architecture du langage — callbacks, événements, promesses, React — repose sur ce principe. Et sur un deuxième : la closure, qu'on verra en fin de chapitre.
// Déclaration : hoistée, utilisable avant sa définition
function additionner(a, b) {
return a + b
}
// Expression
const soustraire = function (a, b) {
return a - b
}
// Fonction fléchée
const multiplier = (a, b) => a * b
const carre = n => n * n
const creerUser = nom => ({ nom, cree: Date.now() }) // parenthèses pour renvoyer un objetLes fléchées ont un corps implicite quand il n'y a pas d'accolades. Elles diffèrent aussi par leur gestion de this, détaillée au chapitre 9.
function saluer(nom = 'inconnu', { majuscules = false, ponctuation = '!' } = {}) {
const msg = `Bonjour ${nom}${ponctuation}`
return majuscules ? msg.toUpperCase() : msg
}
saluer() // 'Bonjour inconnu!'
saluer('Ada', { majuscules: true }) // 'BONJOUR ADA!'Passer un objet d'options déstructuré est le pattern standard dès qu'une fonction a plus de deux paramètres. L'appel devient lisible et l'ordre ne compte plus.
Paramètres rest et spread :
function somme(...nombres) {
return nombres.reduce((acc, n) => acc + n, 0)
}
somme(1, 2, 3) // 6
const valeurs = [4, 5]
somme(...valeurs) // 9
Math.max(...valeurs) // 5JavaScript a une portée lexicale : une fonction voit les variables de l'endroit où elle est écrite, pas de l'endroit où elle est appelée.
const x = 'global'
function externe() {
const x = 'externe'
function interne() {
return x
}
return interne
}
externe()() // 'externe'let et const ont une portée de bloc ({}), var une portée de fonction :
if (true) {
var a = 1
let b = 2
}
a // 1
b // ReferenceErrorUne closure est une fonction qui garde l'accès aux variables de sa portée de création, même après que cette portée a fini de s'exécuter.
function creerCompteur() {
let n = 0
return {
incrementer: () => ++n,
valeur: () => n,
}
}
const c = creerCompteur()
c.incrementer()
c.incrementer()
c.valeur() // 2
c.n // undefined — n est privéen survit parce que les fonctions renvoyées la référencent. C'est le moyen le plus ancien d'avoir des variables privées en JavaScript.
const multiplierPar = facteur => n => n * facteur
const double = multiplierPar(2)
const triple = multiplierPar(3)
double(5) // 10Retarder l'exécution d'une fonction jusqu'à ce que l'utilisateur arrête de taper :
function debounce(fn, delai = 300) {
let timer
return (...args) => {
clearTimeout(timer)
timer = setTimeout(() => fn(...args), delai)
}
}
const rechercher = debounce(q => fetch(`/api/search?q=${encodeURIComponent(q)}`), 250)
input.addEventListener('input', e => rechercher(e.target.value))timer est partagé entre tous les appels grâce à la closure.
function memoize(fn) {
const cache = new Map()
return arg => {
if (!cache.has(arg)) cache.set(arg, fn(arg))
return cache.get(arg)
}
}
const fib = memoize(n => (n < 2 ? n : fib(n - 1) + fib(n - 2)))
fib(90) // instantanéUne fonction qui prend ou renvoie une fonction. Les méthodes de tableau en sont l'exemple le plus courant :
const produits = [
{ nom: 'Clavier', prix: 80, stock: 3 },
{ nom: 'Souris', prix: 25, stock: 0 },
{ nom: 'Écran', prix: 220, stock: 5 },
]
const valeurStock = produits
.filter(p => p.stock > 0)
.map(p => p.prix * p.stock)
.reduce((total, v) => total + v, 0)
// 1340Composition :
const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x)
const slugifier = pipe(
s => s.trim(),
s => s.toLowerCase(),
s => s.normalize('NFD').replace(/[̀-ͯ]/g, ''),
s => s.replace(/[^a-z0-9]+/g, '-'),
s => s.replace(/^-|-$/g, ''),
)
slugifier(' Élégant Titre, Été 2026 ') // 'elegant-titre-ete-2026'Les motifs utilisés ici sont détaillés dans le guide des expressions régulières.
Une fonction pure renvoie toujours le même résultat pour les mêmes entrées et ne modifie rien à l'extérieur. Elle est triviale à tester et à mémoïser.
// Impure : modifie l'argument
function ajouterTag(article, tag) {
article.tags.push(tag)
return article
}
// Pure : renvoie une nouvelle version
const ajouterTagPur = (article, tag) => ({ ...article, tags: [...article.tags, tag] })Une fonction exécutée immédiatement. Historiquement utilisée pour isoler des variables avant les modules :
const config = (() => {
const env = process.env.NODE_ENV ?? 'development'
return { env, debug: env !== 'production' }
})()Écrire throttle(fn, ms) qui exécute fn au plus une fois toutes les ms millisecondes (utile pour le scroll).
function throttle(fn, ms) {
let dernier = 0
return (...args) => {
const maintenant = Date.now()
if (maintenant - dernier >= ms) {
dernier = maintenant
fn(...args)
}
}
}
window.addEventListener('scroll', throttle(() => console.log(scrollY), 100))Retenez la closure : une fonction emporte avec elle les variables qu'elle voit à sa création. Debounce, mémoïsation, modules, hooks React — tous reposent sur ce seul mécanisme.