Кратко
WeakRef — объект-ссылка на другой объект. .deref() возвращает объект или undefined (если GC уже удалил). FinalizationRegistry — callback при удалении объекта. GC timing недетерминирован — нельзя полагаться на порядок удаления.
Подробно
WeakRef: let target = { heavy: 'data' }; const ref = new WeakRef(target);
console.log(ref.deref()); // { heavy: 'data' }
target = null; // объект может быть собран GC
// Позже (GC неопределённо когда) console.log(ref.deref()); // undefined (или объект, если GC не сработал)
FinalizationRegistry:
const registry = new FinalizationRegistry((heldValue) => {
console.log(Объект ${heldValue} удалён);
});
let obj = { data: 'важные данные' }; registry.register(obj, 'myObject');
obj = null; // GC может удалить → callback вызовется
Ограничения:
- .deref() может вернуть undefined в любой момент
- GC timing НЕ детерминирован
- Нельзя полагаться на порядок удаления
- WeakRef + FinalizationRegistry = niche API
Где НЕ использовать:
- Как основной механизм управления памятью
- В критических системах
- Где нужна предсказуемость
Ментальная модель
WeakRef — как адрес пропавшего человека. Вы знаете адрес (ref), но не уверены, жив ли ещё человек (объект). .deref() — проверка: «Ещё здесь?» (undefined — нет). FinalizationRegistry — уведомление от соседей: «Он уехал».
Примеры
**Самый простой:**
let obj = { value: 42 };
const ref = new WeakRef(obj);
console.log(ref.deref()); // { value: 42 }
obj = null;
// GC может удалить объект
// ref.deref() вернёт undefinedПростейший WeakRef: ссылка на объект.
**Простой:**
// FinalizationRegistry
const registry = new FinalizationRegistry((id) => {
console.log(`Cache entry ${id} cleaned up`);
});
function createCachedObject(id) {
const obj = { data: `Cache: ${id}` };
registry.register(obj, id);
return obj;
}
let cache = createCachedObject('user-123');
cache = null; // GC → 'Cache entry user-123 cleaned up'FinalizationRegistry для очистки кэша.
**Реальный пример:**
// WeakRef cache (с проверкой)
class WeakCache {
#cache = new Map();
#registry = new FinalizationRegistry((key) => {
this.#cache.delete(key);
});
get(key) {
const ref = this.#cache.get(key);
if (ref) {
const obj = ref.deref();
if (obj !== undefined) return obj;
this.#cache.delete(key);
}
return undefined;
}
set(key, obj) {
this.#cache.set(key, new WeakRef(obj));
this.#registry.register(obj, key);
}
}Реальный паттерн: WeakRef cache с automatic cleanup.
Частые ошибки
**Неправильно:** Полагаться на .deref() для критических данных
**Почему:** GC может удалить объект в любой момент — .deref() вернёт undefined.
**Правильно:** WeakRef = best-effort. Не используйте для данных, которые обязаны существовать.
**Неправильно:** Думать, что FinalizationRegistry вызывается immediately
**Почему:** FinalizationRegistry callback вызывается НЕ определённо когда (после GC).
**Правильно:** FinalizationRegistry = уведомление, не гарантия.
Важно запомнить
- WeakRef: слабая ссылка на объект
- .deref() возвращает объект или undefined
- FinalizationRegistry: callback при удалении
- GC timing недетерминирован
- Не используйте для критических данных
Связь
Назад: Вы знаете WeakMap/WeakSet (JV5). WeakRef — более низкоуровневый механизм слабых ссылок.
Вперёд: Следующий урок (JV21) — eval — выполнение строк как кода.