Stack, heap et garbage collector
Se représenter la pile, le tas et le ramasse-miettes.
Objectifs
À la fin de cette leçon, vous saurez :
- vous représenter la pile (stack) et le tas (heap) à un niveau conceptuel ;
- relier valeur, référence et zone de mémoire ;
- expliquer le rôle du garbage collector ;
- reconnaître les situations qui retiennent la mémoire inutilement.
🔗 Pour vous rafraîchir la mémoire : objets et références
Deux zones de mémoire
Quand votre programme tourne, JavaScript organise la mémoire en deux grandes zones :
STACK (pile) HEAP (tas)
───────────────────── ─────────────────────
petite, rapide, ordonnée grande, souple
valeurs primitives objets, tableaux, fonctions
contextes d'exécution durée de vie imprévisible
nettoyée automatiquement en sortie libéré par le garbage collector
de fonction
Où vit quoi
let age = 20; // 20 vit dans la stack
const user = { name: "Paul" }; // user : référence dans la stack
// { name: "Paul" } : objet dans le heap
Schéma complet d'un appel :
function exemple() {
let n = 42; // stack : n = 42
const liste = [1, 2]; // stack : référence → heap : [1, 2]
}
// fin d'appel : le contexte est dépilé, n disparaît,
// la référence aussi ; l'objet du heap devient inatteignable.
Le garbage collector
Le ramasse-miettes (garbage collector) parcourt périodiquement le tas et libère tout objet qui n'est plus atteignable — c'est-à-dire qu'aucune référence vivante ne permet plus d'y accéder.
let panier = { items: ["pomme"] };
panier = null; // l'objet { items } n'a plus aucune référence :
// il devient collectable
Trois idées à retenir :
- Rien n'est libéré « immédiatement » : le GC décide de son rythme.
- Un objet référencé quelque part ne sera jamais collecté, même s'il ne sert plus au programme.
- La mémoire n'est pas illimitée : c'est la raison d'être des « fuites ».
Les fuites de mémoire, concrètement
Une fuite survient quand on conserve des références à des données mortes :
const journal = [];
function traiter(donnees) {
journal.push(donnees); // on garde TOUT, pour toujours
}
traiter({ page: 1 });
traiter({ page: 2 });
// ... des milliers d'appels plus tard : le tableau grossit sans fin
Le tableau journal est atteignable, donc jamais collecté. S'il devait ne conserver que les derniers éléments, il faut le limiter explicitement. Autres sources classiques que vous rencontrerez plus tard dans le cursus : écouteurs d'événements jamais retirés, minuteurs non annulés, caches sans limite.
Ce qu'il faut retenir (et ce qu'il ne faut PAS faire)
- Retenez le modèle : variables primitives dans la pile, objets dans le tas, références entre les deux.
- Ne cherchez pas à « optimiser la mémoire » à chaque ligne : le moteur fait très bien son travail tant que vos structures restent simples et que vous ne retenez pas de références inutiles.
- Le réflexe utile : se demander « qui peut encore atteindre cet objet ? » quand une donnée semble oubliée mais toujours présente.
Exercice
- Pour chaque ligne, indiquez stack ou heap :
let total = 0;
const titres = ["a", "b"];
const meta = { taille: 2 };
function creer() {
const local = { valeur: 123 };
return local;
}
const garde = creer();
L'objet local survit-il à la fin de la fonction ? Pourquoi ?
-
Même question sans la dernière ligne (
gardeabsent) : que devient l'objet ? -
Expliquez pourquoi le tableau
journalde cette leçon n'est jamais collecté alors que ses éléments sont « vieux ». -
Proposez une modification simple de
traiterpour ne garder que les 100 derniers appels.
Résumé
- Stack : primitives et références, nettoyées à la sortie de fonction.
- Heap : objets, libérés par le garbage collector quand ils deviennent inatteignables.
- Une fuite = une référence conservée vers des données dont on ne se sert plus.
- Le GC est un allié automatique, pas une excuse à gaspiller.
Correction disponibleCherchez d’abord par vous-même.Voir la correction
Correction
Réponses détaillées
Exercice 1.
total → stack (primitive number)
titres → la référence est dans la stack ; le tableau ["a","b"] dans le heap
meta.taille → la primitive 2 vit dans le heap, à l'intérieur de l'objet
meta → la référence est dans la stack
Exercice 2. Oui, il survit. La fonction retourne la référence de l'objet : elle est copiée dans garde, qui maintient l'objet atteignable depuis l'extérieur de la fonction. C'est exactement le passage de paramètres appliqué aux valeurs de retour.
Exercice 3. Sans variable extérieure qui conserve la référence, l'objet devient inatteignable après le retour de la fonction : le garbage collector le libérera lors d'un passage ultérieur (immédiateté non garantie).
Exercice 4. Le tableau journal reste atteignable pendant toute la vie du programme : le GC ne peut pas savoir que ses anciens éléments ne serviront plus. Atteignable = conservé.
Exercice 5.
function traiter(donnees) {
journal.push(donnees);
if (journal.length > 100) {
journal.shift(); // retire le plus ancien
}
}
La taille du tableau reste bornée : la mémoire consommée ne croît plus avec le nombre d'appels.