Comprenez le fonctionnement du garbage collector, exploitez les références faibles pour éviter les fuites et lissez les traitements coûteux avec debounce et throttle.
Ouvrir cette leçon dans KodokonLe garbage collector de V8 repose sur l'accessibilité : un objet est collectable dès qu'aucune chaîne de références ne le relie aux racines (pile, portées actives, globales). Le GC est générationnel : les objets jeunes vivent dans la *nursery*, collectée souvent et vite (scavenge) ; les survivants sont promus vers l'ancienne génération, traitée par un mark-and-sweep incrémental. Les fuites classiques ne viennent pas du GC mais de vos références oubliées : caches en Map, listeners jamais détachés, closures capturant de gros objets.
const strongCache = new Map();
const weakCache = new WeakMap();
let session = { user: "ada" };
strongCache.set(session, "data");
weakCache.set(session, "data");
session = null;
// Map : la cle retient l'objet -> fuite memoire
// WeakMap : l'entree devient collectableUne WeakMap ne retient pas ses clés : quand la clé devient inaccessible par ailleurs, l'entrée entière disparaît. Conséquences de conception : les clés doivent être des objets (ou des symboles non enregistrés), et la structure n'est ni itérable ni mesurable - exposer sa taille révélerait le comportement du GC, qui est non déterministe. WeakRef va plus loin : elle vous donne une référence faible directe, à déréférencer via deref().
let config = { theme: "dark" };
const ref = new WeakRef(config);
function readTheme() {
const target = ref.deref();
return target ? target.theme : "default";
}
console.log(readTheme()); // "dark"
config = null;
// Apres un passage du GC, deref() peut
// renvoyer undefined : prevoyez un repli.Côté performance perçue, les événements à haute fréquence (scroll, resize, input, mousemove) peuvent déclencher des centaines d'appels par seconde. Deux stratégies complémentaires : debounce n'exécute la fonction qu'après une période de calme (idéal pour une recherche pendant la saisie), tandis que throttle garantit au plus une exécution par intervalle (idéal pour suivre un défilement).
function debounce(fn, delay) {
let timer = null;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(
() => fn.apply(this, args),
delay
);
};
}function throttle(fn, interval) {
let last = 0;
return function (...args) {
const now = Date.now();
if (now - last >= interval) {
last = now;
fn.apply(this, args);
}
};
}ref.deref() sur une WeakRef ?undefined s'il a été collecténull si l'objet a été collecté