Verstehe, wie der Garbage Collector funktioniert, nutze schwache Referenzen, um Lecks zu vermeiden, und glätte teure Arbeit mit Debounce und Throttle.
Diese Lektion in Kodokon öffnenDer Garbage Collector von V8 basiert auf Erreichbarkeit: Ein Objekt wird einsammelbar, sobald keine Referenzkette es mehr mit den Wurzeln (dem Stack, den aktiven Scopes, den Globals) verbindet. Der GC ist generationsbasiert: Junge Objekte leben in der *Nursery*, werden oft und schnell eingesammelt (Scavenge); Überlebende werden in die alte Generation befördert, die von einem inkrementellen Mark-and-Sweep verwaltet wird. Klassische Lecks kommen nicht vom GC, sondern von Referenzen, die du vergessen hast: Map-basierte Caches, Listener, die nie abgehängt werden, Closures, die große Objekte einfangen.
const strongCache = new Map();
const weakCache = new WeakMap();
let session = { user: "ada" };
strongCache.set(session, "data");
weakCache.set(session, "data");
session = null;
// Map: the key retains the object -> memory leak
// WeakMap: the entry becomes collectableEine WeakMap behält ihre Schlüssel nicht: Wird ein Schlüssel von überall sonst unerreichbar, verschwindet der gesamte Eintrag. Folgen für das Design: Schlüssel müssen Objekte sein (oder nicht registrierte Symbole), und die Struktur ist weder iterierbar noch messbar - ihre Größe preiszugeben würde das Verhalten des GC offenbaren, das nicht-deterministisch ist. WeakRef geht weiter: Es gibt dir eine direkte schwache Referenz, die mit deref() dereferenziert wird.
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;
// After a GC pass, deref() may
// return undefined: plan a fallback.Was die gefühlte Performance angeht, können hochfrequente Events (scroll, resize, input, mousemove) Hunderte Aufrufe pro Sekunde auslösen. Zwei sich ergänzende Strategien: Debounce führt die Funktion erst nach einer Ruhephase aus (ideal für die Suche während der Eingabe), während Throttle höchstens eine Ausführung pro Intervall garantiert (ideal, um das Scrollen zu verfolgen).
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() bei einer WeakRef zurückgeben?undefined, wenn es eingesammelt wurdenull, wenn das Objekt eingesammelt wurde