Closure — nima va qanday ishlaydi
Muammodan boshlaylik
function hisoblagich() {
let son = 0;
return function() {
son++;
return son;
};
}
const hisoblash = hisoblagich();
console.log(hisoblash()); // 1
console.log(hisoblash()); // 2
console.log(hisoblash()); // 3
hisoblagich funksiyasi tugadi — lekin son o'zgaruvchisi hali ham tirik. Qaytarilgan funksiya uni "eslab qoldi". Bu — closure.
Closure nima?
Closure — funksiya o'zi yaratilgan scope dagi o'zgaruvchilarni "eslab qolishi". Funksiya tashqi scope tugagandan keyin ham o'sha o'zgaruvchilarga murojaat qila oladi.
Hayotiy o'xshatma: xat. Siz do'stingizga xat yozdingiz — xatda o'sha paytdagi his-tuyg'ularingiz, voqealar bor. Yillar o'tgach xatni o'qisangiz — o'sha paytdagi "kontekst" xatda saqlanib qolgan. Closure — funksiyaning o'z "xati".
Qanday ishlaydi?
Funksiya yaratilganda — u o'zining scope zanjirini "yopib oladi" (closes over). Tashqi funksiya tugagandan keyin ham ichki funksiya tashqi o'zgaruvchilarga murojaat qila oladi.
function tashqi() {
const xabar = "Salom!"; // ← tashqi o'zgaruvchi
function ichki() {
console.log(xabar); // ← closure — xabar ni eslab qoldi
}
return ichki;
}
const fn = tashqi(); // tashqi() tugadi
fn(); // "Salom!" — lekin xabar hali tirik!
tashqi() tugagandan keyin xabar o'chirilishi kerak edi — lekin ichki funksiyasi uni ishlatayotgani uchun xotiradan o'chirilmaydi.
Nima uchun shunday?
Nima uchun closure kerak?
Closure — private holat yaratish imkonini beradi. Ob'ektga o'xshash, lekin tashqaridan to'g'ridan-to'g'ri o'zgartirib bo'lmaydi.
function hisoblagich(boshlangich = 0) {
let son = boshlangich; // ← tashqaridan ko'rinmaydi
return {
oshir: () => ++son,
kamayt: () => --son,
qiymat: () => son,
};
}
const c = hisoblagich(10);
c.oshir(); // 11
c.oshir(); // 12
c.kamayt(); // 11
c.qiymat(); // 11
// son ga to'g'ridan-to'g'ri murojaat qilib bo'lmaydi:
c.son; // undefined — himoyalangan
Amaliy misollar
Bir marta bajariladigan funksiya
function birMarta(fn) {
let bajarildi = false;
let natija;
return function(...args) {
if (!bajarildi) {
natija = fn(...args);
bajarildi = true;
}
return natija;
};
}
const initialize = birMarta(() => {
console.log("Faqat bir marta!");
return 42;
});
initialize(); // "Faqat bir marta!" → 42
initialize(); // 42 — xabar chiqmaydi
initialize(); // 42
Parametr bilan funksiya yaratish (factory)
function ko'paytiruvchi(n) {
return x => x * n; // ← n ni eslab qoladi
}
const ikki_baravar = ko'paytiruvchi(2);
const uch_baravar = ko'paytiruvchi(3);
ikki_baravar(5); // 10
uch_baravar(5); // 15
Memoization — natijani keshlashtirish
function memoize(fn) {
const kesh = {}; // ← closure — kesh saqlanib qoladi
return function(x) {
if (kesh[x] !== undefined) {
return kesh[x]; // ← keshdan qaytaradi
}
kesh[x] = fn(x);
return kesh[x];
};
}
const sekinHisoblash = memoize(n => {
// og'ir hisoblash...
return n * n;
});
sekinHisoblash(5); // hisoblaydi → 25
sekinHisoblash(5); // keshdan → 25 (tez)
Tez-tez uchraydigan xatolar
var bilan sikl va closure:
// ❌ Klassik xato
const funksiyalar = [];
for (var i = 0; i < 3; i++) {
funksiyalar.push(() => console.log(i));
}
funksiyalar[0](); // 3 — kutilgan: 0
funksiyalar[1](); // 3 — kutilgan: 1
funksiyalar[2](); // 3 — kutilgan: 2
Nima uchun? var funksiya scope — barcha funksiyalar bir xil i ga murojaat qiladi. Sikl tugaganda i = 3.
// ✅ let bilan — har iteratsiyada yangi i
for (let i = 0; i < 3; i++) {
funksiyalar.push(() => console.log(i));
}
funksiyalar[0](); // 0 ✅
funksiyalar[1](); // 1 ✅
funksiyalar[2](); // 2 ✅
Xotira sizib chiqishi (memory leak):
function kattaMaʼlumot() {
const kattaMassiv = new Array(1000000).fill("x"); // ← katta xotira
return function() {
return kattaMassiv[0]; // ← faqat birinchi element kerak
// lekin butun massiv xotiradan o'chirilmaydi!
};
}
Closure tashqi o'zgaruvchini tirik saqlaydi — kerak bo'lmasa null ga o'rnatiladi:
let fn = kattaMaʼlumot();
fn(); // ishlatildi
fn = null; // ← xotira bo'shatiladi
Xulosa
Closure — funksiya o'zi yaratilgan scope dagi o'zgaruvchilarni eslab qolishi. Tashqi funksiya tugagandan keyin ham ishlaydi.
Asosiy ishlatilishi:
- Private holat — tashqaridan o'zgartirib bo'lmaydigan o'zgaruvchilar
- Factory funksiyalar — parametr bilan funksiya yaratish
- Memoization — natijalarni keshlash
- Bir marta bajariladigan funksiyalar
var bilan sikl + closure — klassik xato. let ishlatiladi.
Keyingi dars
12-dars: Higher Order Functions — funksiyani parametr va qaytish qiymati sifatida