Cả hai cho phép tương tác với garbage collector, nhưng đều mang tính advisory (không đảm bảo thời điểm).
- WeakRef giữ một tham chiếu yếu tới object: không ngăn GC thu hồi object đó. Gọi
.deref()để lấy lại object — trả vềundefinednếu đã bị thu hồi. - FinalizationRegistry đăng ký một callback chạy sau khi một object bị GC dọn, để dọn tài nguyên đi kèm (cache entry, file handle).
const reg = new FinalizationRegistry((heldValue) => {
console.log('đã thu hồi:', heldValue);
});
let obj = { id: 42 };
const ref = new WeakRef(obj);
reg.register(obj, 'obj#42');
// ... obj = null; sau một lúc GC chạy → callback in 'obj#42'
ref.deref(); // {id:42} hoặc undefined nếu đã bị thuTại sao hạn chế: thời điểm và việc callback có chạy hay không không đảm bảo — khác nhau giữa các engine, có thể không chạy khi tab đóng. Logic đúng đắn của app không được phụ thuộc vào nó. Phù hợp cho cache hỗ trợ (như WeakValueMap), không phù hợp cho cleanup bắt buộc (dùng try/finally, using/Symbol.dispose).
Lưu ý: đừng dùng deref() nhiều lần trong một tick rồi giả định kết quả đồng nhất sau đó.
Both let you interact with the garbage collector, but both are advisory (no timing guarantees).
- WeakRef holds a weak reference to an object: it doesn't stop GC from reclaiming it. Call
.deref()to get the object back —undefinedif already collected. - FinalizationRegistry registers a callback that runs after an object is GC'd, to clean up associated resources (cache entry, file handle).
const reg = new FinalizationRegistry((held) => console.log('collected:', held));
let obj = { id: 42 };
const ref = new WeakRef(obj);
reg.register(obj, 'obj#42');
ref.deref(); // {id:42} or undefined if collectedWhy restraint: when, or whether, the callback runs is not guaranteed — it varies by engine and may never fire (e.g. tab closed). Correctness must not depend on it. Fine for backing caches, not for mandatory cleanup (use try/finally or using/Symbol.dispose).
Note: don't call deref() repeatedly in one tick and assume consistent later results.