Closure’lar

JavaScript o‘zgaruvchilari quyidagilarga tegishli bo‘lishi mumkin:

  • Lokal ko‘rinish sohasiga (local scope)
  • Global miqyos

Global o‘zgaruvchilarni closure’lar yordamida lokal (xususiy) qilish mumkin.

Yopish funksiyaga "xususiy" o‘zgaruvchilarga ega bo‘lish imkonini beradi.

Funksiya tashqi ko‘rinishdagi o‘zgaruvchilarni eslab qolganda, hatto tashqi funksiyani bajarishni tugatgandan keyin ham yopish hosil bo‘ladi.

Closure’lar — murakkab mavzu.

Avval JavaScript funksiyalari va ko‘rinish sohasini (scope) tushunib olganingizga ishonch hosil qiling.

JavaScript Functionlar

JavaScript doirasi

ULASHISH

Mahalliy o‘zgaruvchilar

Lokal o‘zgaruvchi — funksiya ichida aniqlangan "xususiy" o‘zgaruvchi.

Ma’lumot mahalliy miqyosdagi barcha o‘zgaruvchilarga kirishi mumkin.

Misol

a — funksiya ichida aniqlangan lokal o‘zgaruvchi:

function myFunction() {
  let a = 4;
  return a * a;
}
O‘zingiz sinab ko‘ring »

Global o‘zgaruvchilar

Global o‘zgaruvchi — funksiyadan tashqarida aniqlangan "ommaviy" o‘zgaruvchi.

Ma’lumot Global Scope (Global Scope)dagi barcha o‘zgaruvchilarga kirishi mumkin:

Misol

a — funksiyadan tashqarida aniqlangan global o‘zgaruvchi:

let a = 4;
function myFunction() {
  return a * a;
}
O‘zingiz sinab ko‘ring »

Veb-sahifada global o‘zgaruvchilar sahifaga tegishli.

Global o‘zgaruvchilardan sahifadagi barcha skriptlar foydalanishi (yoki ularni o‘zgartirishi) mumkin.

Mahalliy o‘zgaruvchidan faqat u aniqlangan funksiya ichida foydalanish mumkin. Bu shaxsiy va boshqa funksiyalardan va boshqa skript kodlaridan yashirin.

Xuddi shu nomdagi global va mahalliy o‘zgaruvchilar turli xil o‘zgaruvchilardir. Birini o‘zgartirish ikkinchisini o‘zgartirmaydi.

E’lon qilinmagan o‘zgaruvchilar (var, let, const kalit so‘zisiz yaratilgan), hatto ular funksiya ichida yaratilgan bo‘lsa ham, har doim globaldir.

Misol

a o‘zgaruvchisi global o‘zgaruvchidir, chunki u e’lon qilinmagan:

function myFunction() {
  a = 4;
}
O‘zingiz sinab ko‘ring »


O‘zgaruvchining yashash muddati

Global o‘zgaruvchilar sahifa o‘chirilmaguncha, masalan, boshqa sahifaga o‘tayotganingizda yoki oynani yopganingizda yashaydi.

Mahalliy o‘zgaruvchilar qisqa umrga ega. Ular funksiya chaqirilganda yaratiladi va funksiya tugagach o‘chiriladi.


Hisoblagich muammosi

Aytaylik, siz biror narsani sanash uchun o‘zgaruvchidan foydalanmoqchisiz va bu hisoblagich hamma uchun (barcha funksiyalar uchun) mavjud bo‘lishini xohlaysiz.

Hisoblagichni oshirish uchun global o‘zgaruvchidan va yordamdan foydalanishingiz mumkin:

Misol

// Initiate counter
let counter = 0;

// Function to increment counter
function add() {
  counter += 1;
}

// Call add() 3 times
add();
add();
add();

// The counter should now be 3
O‘zingiz sinab ko‘ring »

Ogohlantirish!

Yuqoridagi yechim bilan bog‘liq muammo bor: sahifadagi istalgan kod add() ni chaqirmasdan hisoblagichni o‘zgartirishi mumkin.

Hisoblagich boshqa kod o‘zgarishini oldini olish uchun add() funksiyasi uchun mahalliy bo‘lishi kerak bu:

Misol

// Initiate counter
let counter = 0;

// Function to increment counter
function add() {
  let counter = 0;
  counter += 1;
}

// Call add() 3 times
add();
add();
add();

// The counter should now be 3. But it is 0
O‘zingiz sinab ko‘ring »

Bu ishlamadi, chunki biz mahalliy hisoblagich o‘rniga global hisoblagichni ko‘rsatamiz.

Biz global hisoblagichni olib tashlashimiz va funksiyani qaytarishiga ruxsat berish orqali mahalliy hisoblagichga kirishimiz mumkin:

Misol

// Function to increment counter
function add() {
  let counter = 0;
  counter += 1;
  return counter;
}

let x= 0;
// Call add() 3 times
x = add();
x = add();
x = add();

// The counter should now be 3. But it is 1.
O‘zingiz sinab ko‘ring »

Bu ishlamadi, chunki biz funksiyani har chaqirganimizda mahalliy hisoblagichni qayta tiklaymiz.

Solution

JavaScript ichki funksiyasi buni hal qilishi mumkin.

JavaScript’da ichma-ich funksiyalar

Barcha funksiyalar global miqyosga kirish huquqiga ega.

Aslida, JavaScript-da barcha funksiyalar ularning "yuqorida" doirasiga kirish huquqiga ega.

JavaScript ichki o‘rnatilgan funksiyalarni qo‘llab-quvvatlaydi. Ichki funksiyalar ularning "yuqorida" doirasiga kirish huquqiga ega.

Misol

plus() ichki funksiyasi kirish huquqiga ega asosiy funksiyadagi counter o‘zgaruvchisiga:

function add() {
  let counter = 0;
  function plus() {counter += 1;}
  plus();   
  return counter;
}
O‘zingiz sinab ko‘ring »

Agar biz tashqaridan plus() funksiyasiga erisha olsak, bu qarshi dilemmani hal qilishi mumkin edi.

Shuningdek, biz counter = 0 ni faqat bir marta bajarish usulini topishimiz kerak.

Solution

Bizga closure kerak.

JavaScript Closures (Yopiq funksiyalar)

Misol

function myCounter() {
  let counter = 0;
  return function() {
    counter++;
    return counter;
  };
}
const add = myCounter();
add();
add();
add();

// the counter is now 3
O‘zingiz sinab ko‘ring »

Misol tahlili

add o‘zgaruvchisi funksiyaning qaytariladigan qiymatiga tayinlangan.

Funksiya faqat bir marta ishga tushadi. U hisoblagichni nolga (0) o‘rnatadi va funksiya ifodasini qaytaradi.

Shu tarzda qo‘shish funksiyaga aylanadi. "Ajoyib" tomoni shundaki, u o‘zining asosiy doirasidagi hisoblagichga kira oladi.

Bu closure (yopiq funksiya) deb ataladi. U funksiyaga "xususiy" (private) o‘zgaruvchilarga ega bo‘lish imkonini beradi.

Hisoblagich myCounter funksiyasi bilan himoyalangan va uni faqat qo‘shish funksiyasi yordamida o‘zgartirish mumkin.


Conclusion

Yopish - bu ota-ona funksiyasi yopilgandan keyin ota-ona doirasiga kirish huquqiga ega bo‘lgan Function.

Closure’lar tarixan quyidagilar uchun ishlatilgan:

  • Create private variables
  • Preserve state between function calls
  • Let va const mavjud bo‘lgunga qadar blok ko‘lamini simulyatsiya qiling
  • Currying va memoization kabi ayrim dizayn patternlarini amalga oshirish

Eski JavaScript kodida closure’lar ko‘p uchraydi, ammo zamonaviy JavaScript’da closure’lar unchalik tez-tez ishlatilmaydi.

ECMAScript 2015 va undan keyingi JavaScript versiyalari closure’larga muqobil bo‘lgan yangi til imkoniyatlarini taqdim etdi.


Zamonaviy muqobil: klassning xususiy maydonlari

ECMAScript 2022 dan boshlab JavaScript # sintaksisi yordamida haqiqiy xususiy (private) klass maydonlarini qo‘llab-quvvatlaydi.

Shaxsiy maydonlar til tomonidan qo‘llaniladi va ularga sinfdan tashqarida kirish mumkin emas.

Barcha zamonaviy brauzerlar klasslarning xususiy maydonlarini (private class fields) qo‘llab-quvvatlaydi.

Misol

class Counter {
  #count = 0;

  increment() {
    this.#count++;
    return this.#count;
  }
}

const myCounter = new Counter();
myCounter.increment();

Sinflar bilan ishlashda odatda xususiy class maydonlariga afzallik beriladi.

  • They provide true privacy.
  • Ular klasslar ichidagi closure’ga asoslangan patternlardan soddaroq.
  • Ular rasmiy ECMAScript standartining bir qismidir.

Closures (yopiq funksiyalar) hali ham muhim va darsdan tashqari foydalidir.

Yopishlar eski kod bazalari va funktsional dasturlash naqshlarida ham keng qo‘llaniladi.



W3Schools Pathfinder

Yutuqlaringizni kuzating – bu bepul!