WeakRef va FinalizationRegistry
Odatda obyektga havola bo'lsa, u xotirada saqlanadi โ axlat yig'uvchi (garbage collector) uni o'chirmaydi. WeakRef esa zaif havola yaratadi: u obyekt yashashini kafolatlamaydi, shuning uchun kerak bo'lganda obyekt xotiradan tozalanishi mumkin.
Odatiy (kuchli) havola muammosi
Oddiy havola obyektni "ushlab turadi". Kesh (cache) yasaganda bu muammo: keshdagi obyekt boshqa hech kimga kerak bo'lmasa ham, kesh uni ushlab turgani uchun xotira bo'shamaydi.
WeakRef shu muammoni yechadi โ u obyektga ushlab turmaydigan havola beradi.
let obyekt = { data: "katta ma'lumot" };
let zaifHavola = new WeakRef(obyekt);
// obyektga murojaat qilish uchun deref() ishlatiladi
let olingan = zaifHavola.deref();
WeakMap/WeakSetdan farqi: ular butun kolleksiyani zaiflashtiradi, WeakRef esa bitta obyektga nozik nazorat beradi.deref() metodi
Zaif havoladan obyektni olish uchun deref() chaqiriladi. Agar obyekt hali xotirada bo'lsa โ o'zini qaytaradi; allaqachon tozalangan bo'lsa โ undefined:
let havola = new WeakRef({ name: "Ali" });
let obyekt = havola.deref();
if (obyekt !== undefined) {
// obyekt hali mavjud, ishlatsa bo'ladi
console.log(obyekt.name);
} else {
// obyekt tozalangan
console.log("Obyekt yo'q qilingan");
}
deref() chaqirganda natijani albatta tekshiring. U istalgan vaqtda undefined qaytarishi mumkin โ hech qachon obyekt mavjudligiga ishonch bilan yondashmang.Kesh misoli
WeakRefning tipik qo'llanishi โ xotirani band qilmaydigan kesh. Quyida rasmlarni keshlash misoli: agar keshdagi obyekt hali xotirada bo'lsa, uni qayta ishlatamiz; bo'lmasa qaytadan yaratamiz.
let kesh = new Map();
function rasmOlish(nom) {
let havola = kesh.get(nom);
let rasm = havola ? havola.deref() : undefined;
if (rasm === undefined) {
// yo'q yoki tozalangan - qaytadan yaratamiz
rasm = { nom: nom, data: "...og'ir ma'lumot..." };
kesh.set(nom, new WeakRef(rasm));
}
return rasm;
}
let a = rasmOlish("logo.png");
let b = rasmOlish("logo.png");
// a va b bir xil obyekt (kesh ishladi)
Bu keshning afzalligi: agar tizimga xotira kerak bo'lsa, keshdagi ishlatilmayotgan rasmlar avtomatik tozalanadi. Kamchiligi: Map ichida bo'sh WeakReflar qolib ketishi mumkin โ ularni tozalash uchun FinalizationRegistry kerak.
FinalizationRegistry
FinalizationRegistry โ obyekt axlat yig'uvchi tomonidan yo'q qilingach, tozalash funksiyasini (callback) chaqirish imkonini beradi. U shunday yaratiladi:
let registry = new FinalizationRegistry((qiymat) => {
// obyekt yo'q qilingach chaqiriladi
console.log("Tozalandi: " + qiymat);
});
Kuzatiladigan obyektni register orqali ro'yxatga olamiz. Ikkinchi argument โ obyekt yo'q qilingach callbackka uzatiladigan qiymat (odatda kalit yoki nom):
let obyekt = { name: "Ali" };
registry.register(obyekt, "Ali-obyekti");
// obyektga havola yo'qolgach va u tozalangach,
// callback "Ali-obyekti" bilan chaqiriladi
Yuqoridagi kesh misolini FinalizationRegistry bilan to'ldirib, tozalangan obyektning "bo'sh" yozuvini Mapdan ham o'chirib tashlaymiz:
let kesh = new Map();
let registry = new FinalizationRegistry((nom) => {
// obyekt tozalandi -> Map'dan ham o'chiramiz
let havola = kesh.get(nom);
if (havola && havola.deref() === undefined) {
kesh.delete(nom);
}
});
function saqlash(nom, obyekt) {
kesh.set(nom, new WeakRef(obyekt));
registry.register(obyekt, nom);
}
Ehtiyotkorlik
WeakRef va FinalizationRegistry โ kuchli, ammo nozik vositalar. Ularni ehtiyotkorlik bilan ishlating:
- Axlat yig'uvchi qachon ishlashini bashorat qilib bo'lmaydi โ callback darhol yoki umuman chaqirilmasligi mumkin;
- Tozalash callbackiga muhim mantiqni yuklamang โ u ishga tushishiga kafolat yo'q;
- Bir necha obyekt bir vaqtda tozalansa, callbacklar tartibi noaniq;
- Bu vositalarni faqat optimallashtirish uchun ishlating, dasturning to'g'riligi ularga bog'liq bo'lmasin.
FinalizationRegistry callbacki umuman chaqirilmasligi ham mumkin โ masalan, dastur tugab qolsa. Shuning uchun unga tayanib fayl yopish yoki tarmoq ulanishini uzish kabi zarur amallarni bajarmang.WeakMap yoki WeakSet yetarli va xavfsizroq. WeakRef/FinalizationRegistryga faqat chindan nozik xotira nazorati kerak bo'lgandagina murojaat qiling.Xulosa
WeakRefobyektga zaif havola beradi โ u obyekt yashashini kafolatlamaydi;deref()obyektni yoki (tozalangan bo'lsa)undefinedqaytaradi โ doim tekshiring;- Tipik qo'llanishi โ xotirani band qilmaydigan kesh;
FinalizationRegistryobyekt tozalangach callback chaqiradi (masalan, keshni tozalash uchun);- Axlat yig'uvchi xatti-harakati noaniq โ bu vositalarga dastur to'g'riligini bog'lamang, faqat optimallashtirish uchun ishlating.