ガベージコレクタの仕組みを理解し、弱参照を使ってリークを避け、debounce と throttle で高コストな処理を平準化します。
このレッスンを Kodokon で開くV8 のガベージコレクタは到達可能性(reachability)に基づいています。オブジェクトは、それをルート(スタック、アクティブなスコープ、グローバル)につなぐ参照の連鎖がなくなった途端、回収可能になります。GC は世代別(generational)です。若いオブジェクトは *nursery* に住み、頻繁かつ高速に回収されます(scavenge)。生き残ったものは旧世代に昇格し、インクリメンタルなマーク・アンド・スイープで扱われます。古典的なリークは GC が原因ではなく、あなたが忘れた参照が原因です。Map ベースのキャッシュ、決して外されないリスナー、大きなオブジェクトをキャプチャするクロージャなどです。
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 collectableWeakMap はキーを保持しません。キーが他のどこからも到達不能になると、エントリ全体が消えます。設計上の帰結はこうです。キーはオブジェクト(または未登録のシンボル)でなければならず、この構造は反復も計測もできません。そのサイズを公開してしまうと、非決定的な GC の挙動が露見してしまうからです。WeakRef はさらに踏み込み、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;
// After a GC pass, deref() may
// return undefined: plan a fallback.体感パフォーマンスの側面では、高頻度のイベント(scroll、resize、input、mousemove)は 1 秒に数百回もの呼び出しを引き起こしかねません。相補的な 2 つの戦略があります。debounce は静かな期間が続いたあとにのみ関数を実行します(入力しながらの検索に理想的)。一方throttle は間隔ごとに最大 1 回の実行を保証します(スクロールの追跡に理想的)。
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() は何を返しうるでしょうか?undefinednull