Mundarija (30)
- Bu darsda
- 1. Nega bu kerak?
- 2. IIFE nima?
- 2.1 Function expression'dan IIFE'gacha
- 2.2 Nega qavs kerak?
- 2.3 Arrow funksiya bilan
- 2.4 IIFE'ga argument berish
- 3. IIFE va scope: o'zgaruvchilarni yashirish
- 3.1 Ichkaridagi ichkarida qoladi
- 3.2 Qoralama daftar: IIFE qiymat qaytaradi
- 3.3 IIFE bugun qanchalik kerak?
- 4. Funksiya — bu ham obyekt
- 4.1 Funksiyada ham "nuqta" bor
- 4.2 fn.name — funksiya nomi
- 4.3 fn.length — nechta parametr kutadi
- 4.4 Funksiyaga o'z xususiyatingizni qo'shish
- 5. Nomli funksiya ifodasi (named function expression)
- 5.1 Nom faqat ichkarida ko'rinadi
- 5.2 Nega bu foydali?
- 6. Ko'p uchraydigan xatolar
- 6.1 IIFE'ni qavssiz yozish
- 6.2 Oldingi qatorda nuqta-vergul yo'q
- 6.3 name ni o'zgartirishga urinish
- 6.4 length argumentlar sonini beradi deb o'ylash
- 7. Mashqlar
- 1-mashq (oson): Salomlashuvchi IIFE
- 2-mashq (o'rta): Nom va parametrlar
- 3-mashq (qiyin): Taksi hisoblagichi
- 8. Real ishda
- Xulosa
JavaScript IIFE: darhol chaqiriladigan funksiya va funksiya obyekt sifatida
Qisqacha: IIFE (Immediately Invoked Function Expression) — yozilgan zahoti bir marta ishlaydigan funksiya:
(function () { ... })();. U ichidagi o'zgaruvchilarni tashqi koddan yashiradi. Bundan tashqari JavaScript'da funksiya — maxsus obyekt: uningnamevalengthxususiyatlari bor, unga o'zingiz ham xususiyat qo'sha olasiz.
Bu darsda
- IIFE yoza olasiz va nega u qavs ichiga olinishini tushuntira olasiz.
- IIFE yordamida o'zgaruvchilarni umumiy (global) scope'dan yashira olasiz.
- Nomli funksiya ifodasini (named function expression) yozasiz va uning nomi qayerda ko'rinishini bilasiz.
fn.namevafn.lengthnima qaytarishini oldindan ayta olasiz.- Funksiyaga o'z xususiyatingizni qo'shib, masalan, chaqiruvlar sonini sanay olasiz.
Oldin bilishingiz kerak: Function expression va arrow funksiyalar, Scope asoslari, Funksiya — qiymat: callback va HOF, Rekursiya asoslari.
1. Nega bu kerak?
O'tgan darsda funksiya o'zini o'zi chaqirdi. Bugun funksiyaga boshqa tomondan qaraymiz. Avval bitta amaliy muammo.
Jasur va Malika bitta do'kon sayti ustida ishlayapti. Har biri o'z skriptini yozdi va ikkalasi ham bitta sahifaga ulandi:
<script>
let narx = 25000;
console.log("Jasurning skripti:", narx);
</script>
<script>
let narx = 40000;
console.log("Malikaning skripti:", narx);
</script>Sahifani ochsangiz, konsolda qizil xato chiqadi:
Uncaught SyntaxError: Identifier 'narx' has already been declaredBrauzerda oddiy <script> teglarining eng tashqi o'zgaruvchilari bitta umumiy joyda — global scopeda yashaydi. Ikki dasturchi bir-birining nomini bilmaydi, lekin nomlar to'qnashdi. Katta saytda o'nlab skript bo'ladi — bunday to'qnashuv muqarrar.
Yechim — har kim o'z kodini funksiya ichiga "o'rashi". Scope darsida ko'rganimizdek, funksiya ichidagi o'zgaruvchi tashqariga ko'rinmaydi. Faqat bu funksiya yozilgan zahoti bir marta ishlashi kerak. Aynan shunday funksiya — IIFE.
2. IIFE nima?
2.1 Function expression'dan IIFE'gacha
Function expression darsida funksiyani o'zgaruvchiga saqlashni o'rgandik:
const salom = function () {
console.log("Assalomu alaykum!");
};
salom(); // Assalomu alaykum!Bu yerda salom — funksiyani ushlab turgan nom, () esa uni chaqiradi. Savol: funksiya faqat bir marta kerak bo'lsa, nomga saqlash shartmi? Yo'q. Funksiya ifodasini qavsga olib, darhol chaqirish mumkin:
(function () {
console.log("Assalomu alaykum!");
})();Konsolda:
Assalomu alaykum!IIFE (Immediately Invoked Function Expression) — "darhol chaqiriladigan funksiya ifodasi". U yozilgan joyning o'zida bir marta ishlaydi va boshqa hech qachon chaqirilmaydi.
Keling, qismlarini ajratamiz:
| Qism | Vazifasi |
|---|---|
(function () { ... }) |
Funksiya ifodasi, qavs ichida |
() |
Uni darhol chaqiradi |
; |
Ko'rsatma tugadi |
2.2 Nega qavs kerak?
Qavssiz yozib ko'raylik:
function () {
console.log("Assalomu alaykum!");
}();SyntaxError: Function statements require a function nameTarjimasi: "Funksiya e'loniga nom kerak". JavaScript satr boshida function so'zini ko'rsa, uni e'lon (declaration) deb tushunadi. E'longa esa nom shart va uni shu zahoti chaqirib bo'lmaydi.
Tashqi qavs JavaScript'ga boshqacha xabar beradi: "bu e'lon emas, ifoda — qiymat". Qiymat bo'lgan funksiyani esa darhol chaqirsa bo'ladi.
2.3 Arrow funksiya bilan
Arrow funksiyadan ham IIFE yasash mumkin. Zamonaviy kodda ko'pincha shunday yoziladi:
(() => {
console.log("Arrow IIFE ishladi");
})();Konsolda:
Arrow IIFE ishladi2.4 IIFE'ga argument berish
IIFE — oddiy funksiya, shuning uchun parametr ham oladi. Argument oxirgi qavs ichiga yoziladi:
(function (ism, shahar) {
console.log(`Xush kelibsiz, ${ism}! Shahar: ${shahar}`);
})("Malika", "Samarqand");Konsolda:
Xush kelibsiz, Malika! Shahar: SamarqandTekshirib ko'ring: Quyidagi kod konsolga nima chiqaradi va necha marta?
js(function (son) { console.log(son * 2); })(21);
Javob
42 — bir marta. Funksiya 21 argumenti bilan darhol chaqirildi va 21 * 2 ni chiqardi. Uni qayta chaqirib bo'lmaydi: funksiyaning nomi ham, uni saqlagan o'zgaruvchi ham yo'q.
3. IIFE va scope: o'zgaruvchilarni yashirish
3.1 Ichkaridagi ichkarida qoladi
IIFE ichida e'lon qilingan o'zgaruvchi tashqariga chiqmaydi:
(function () {
const chegirma = 15;
console.log(`Bugun chegirma: ${chegirma}%`);
})();
console.log(typeof chegirma);Konsolda:
Bugun chegirma: 15%
undefinedTashqarida chegirma degan nom umuman yo'q. typeof darsida ko'rganimizdek, noma'lum nom uchun typeof xato bermay "undefined" qaytaradi.
Endi Jasur va Malikaning muammosini hal qilamiz. Har biri o'z kodini IIFE'ga o'raydi:
<script>
(function () {
let narx = 25000;
console.log("Jasurning skripti:", narx);
})();
</script>
<script>
(function () {
let narx = 40000;
console.log("Malikaning skripti:", narx);
})();
</script>Endi ikkala narx har biri o'z funksiyasining ichida yashaydi. Ular bir-birini ko'rmaydi va xato yo'q.
3.2 Qoralama daftar: IIFE qiymat qaytaradi
Imtihonda murakkab misolni qoralamada hisoblaysiz. Javobni toza varaqqa ko'chirasiz, qoralamani esa tashlaysiz. IIFE ham shunday ishlay oladi: ichida vaqtinchalik o'zgaruvchilar, tashqariga faqat natija chiqadi.
const yetkazishNarxi = (function () {
const asosiy = 10000; // vaqtinchalik
const masofa = 7; // km, vaqtinchalik
const kmNarxi = 2000; // vaqtinchalik
return asosiy + masofa * kmNarxi;
})();
console.log(yetkazishNarxi); // 24000yetkazishNarxi ga funksiya emas, uning natijasi yozildi — 24000. asosiy, masofa, kmNarxi esa IIFE tugagach "tashlab yuborildi". Bu usul const ni bir necha qadamli hisob bilan to'ldirish kerak bo'lganda qulay.
3.3 IIFE bugun qanchalik kerak?
IIFE 2015-yilgacha (ES6'dan oldin) juda keng ishlatilgan. O'shanda let, const va modullar yo'q edi — o'zgaruvchini yashirishning yagona yo'li funksiya edi.
Bugun bu vazifani ko'pincha boshqa vositalar bajaradi:
- Blok
{ }—letvaconstblok ichida qoladi, funksiya shart emas. - Modullar —
<script type="module">yoki alohida JS fayl o'z scope'iga ega. Ularni modullar darsida o'rganamiz.
Lekin IIFE'ni hali ko'p uchratasiz: eski kodda, sayt statistikasi skriptlarida, bundler (kodni bitta faylga yig'uvchi vosita) chiqargan fayllarda. Asinxron kodda (async () => { ... })() shakli ham bor — uni async/await darsida ko'ramiz.
Tekshirib ko'ring:
const natija = (() => 5 * 5)();qatoridan keyinnatijanimaga teng: funksiyagami yoki songami?
Javob
Songa — 25. Oxiridagi () funksiyani darhol chaqirdi, natija ga esa chaqiruv qaytargan qiymat yozildi. Agar oxirgi () bo'lmaganida, natija funksiyaning o'zi bo'lardi.
4. Funksiya — bu ham obyekt
4.1 Funksiyada ham "nuqta" bor
Satrlar bilan ishlaganda .length ni ko'p ishlatdingiz:
console.log("Toshkent".length); // 8Nuqtadan keyingi length — satrning xususiyati (property). Xususiyat — qiymatga biriktirilgan nomli ma'lumot. Masalan, pasport — odamning "obyekti", undagi ism va tug'ilgan yil esa uning xususiyatlari.
Endi kutilmagan narsa: funksiyaning ham xususiyatlari bor!
function buyurtmaBer(taom, soni) {
console.log(`${soni} ta ${taom} buyurtma qilindi`);
}
console.log(buyurtmaBer.name); // buyurtmaBer
console.log(buyurtmaBer.length); // 2
console.log(typeof buyurtmaBer); // functionMa'lumot turlari darsida JavaScript'da primitiv turlar va obyekt borligini ko'rgan edik. Funksiya obyektlar oilasiga kiradi — u "chaqirsa bo'ladigan maxsus obyekt". typeof unga alohida "function" javobini beradi, lekin ichida u obyekt. Obyektlarni obyektlar darsida to'liq o'rganamiz. Hozir funksiyaning ikki muhim xususiyatini ko'ramiz.
4.2 fn.name — funksiya nomi
name — funksiyaning nomi, satr ko'rinishida. JavaScript uni turli yozuvlarda turlicha aniqlaydi:
function salom() {}
const xayr = function () {};
const rahmat = () => {};
const tolov = function click() {};
console.log(salom.name); // salom
console.log(xayr.name); // xayr
console.log(rahmat.name); // rahmat
console.log(tolov.name); // click| Yozuv | name |
Qayerdan olindi |
|---|---|---|
function salom() {} |
"salom" |
E'londagi nom |
const xayr = function () {} |
"xayr" |
O'zgaruvchi nomidan |
const rahmat = () => {} |
"rahmat" |
O'zgaruvchi nomidan |
const tolov = function click() {} |
"click" |
Funksiyaning o'z nomi ustun |
Nomsiz funksiya to'g'ridan-to'g'ri ishlatilsa, name bo'sh satr bo'ladi. Masalan, callback sifatida berilganda:
function nominiAyt(fn) {
console.log(`Nomi: "${fn.name}"`);
}
nominiAyt(function hisobla() {});
nominiAyt(() => {});Konsolda:
Nomi: "hisobla"
Nomi: ""Nega nom muhim? Xato chiqqanda JavaScript qaysi funksiyada ekanini aynan shu nom bilan ko'rsatadi. Nomsiz funksiya xato xabarida va DevTools'da (anonymous) — "nomsiz" deb ko'rinadi. Nomsiz funksiyalar ko'p bo'lsa, xatoni qidirish qiyinlashadi.
4.3 fn.length — nechta parametr kutadi
length — funksiya e'lonida nechta parametr yozilganini ko'rsatadi. Nechta argument berilgani emas, nechta kutilgani:
function yetkazish(manzil, vaqt) {}
function salomlash() {}
function tolov(summa, valyuta = "so'm", izoh) {}
console.log(yetkazish.length); // 2
console.log(salomlash.length); // 0
console.log(tolov.length); // 1Oxirgi natijaga e'tibor bering: tolov da uchta parametr, lekin length — 1. Qoida: default qiymatli parametr va undan keyingilar sanalmaydi. length faqat birinchi default'gacha bo'lgan "majburiy" parametrlarni sanaydi.
Kundalik kodda length kam ishlatiladi. U ko'proq kutubxonalar ichida kerak bo'ladi. Masalan, Express (Node.js server kutubxonasi) to'rt parametrli funksiyani oddiy funksiyadan farqlab, uni xatolarni ushlovchi deb taniydi.
Tekshirib ko'ring:
const f = (a, b = 1, c) => {};uchunf.namevaf.lengthnimaga teng?
Javob
f.name — "f": arrow funksiya nomni o'zgaruvchidan oldi. f.length — 1: b default qiymatli, shuning uchun sanash shu yerda to'xtaydi. c ning default'i yo'q, lekin u b dan keyin kelgani uchun sanalmaydi.
4.4 Funksiyaga o'z xususiyatingizni qo'shish
Funksiya obyekt bo'lgani uchun unga o'zingiz ham xususiyat qo'sha olasiz. Masalan, funksiya necha marta chaqirilganini sanaymiz:
function taksiChaqir(manzil) {
taksiChaqir.soni++;
console.log(`${taksiChaqir.soni}-buyurtma: ${manzil}`);
}
taksiChaqir.soni = 0; // yangi xususiyat
taksiChaqir("Chorsu");
taksiChaqir("Amir Temur xiyoboni");
console.log(`Jami: ${taksiChaqir.soni} ta`);Konsolda:
1-buyurtma: Chorsu
2-buyurtma: Amir Temur xiyoboni
Jami: 2 tataksiChaqir.soni = 0 qatori funksiyaga soni degan yangi xususiyat qo'shdi. Hisoblagich alohida global o'zgaruvchida emas, funksiyaning o'zida saqlanyapti. Endi u funksiyadan ajralib qolmaydi.
Funksiyani console.log bilan chiqarsangiz, qo'shgan xususiyatingiz ham ko'rinadi:
function taksiChaqir(manzil) {}
taksiChaqir.soni = 2;
console.log(taksiChaqir); // [Function: taksiChaqir] { soni: 2 }{ soni: 2 } — funksiyaga biriktirilgan xususiyat. Jingalak qavsli bu yozuvni obyektlar darsida batafsil ko'ramiz. Brauzer konsolida ko'rinish biroz boshqacha bo'lishi mumkin — funksiya matni chiqadi, xususiyatlarni esa console.dir(taksiChaqir) bilan ochib ko'rasiz.
Maslahat: Funksiyaga xususiyat qo'shish — kam uchraydigan usul. Hisoblagich va shunga o'xshash "xotira"ni zamonaviy kodda ko'pincha closure bilan yozishadi. Uni closure darsida o'rganamiz. Bu yerdagi asosiy g'oya boshqa: funksiya ham qiymat, ham obyekt.
5. Nomli funksiya ifodasi (named function expression)
5.1 Nom faqat ichkarida ko'rinadi
Yuqorida const tolov = function click() {} ni ko'rdik. Bu — nomli funksiya ifodasi (named function expression): o'z nomi bor funksiya ifodasi. Uning nomi faqat funksiyaning ichida ko'rinadi:
const faktorial = function hisobla(n) {
if (n <= 1) {
return 1;
}
return n * hisobla(n - 1); // ichkarida hisobla ko'rinadi
};
console.log(faktorial(5)); // 120Tashqaridan esa hisobla degan nom yo'q:
const faktorial = function hisobla(n) {
return n <= 1 ? 1 : n * hisobla(n - 1);
};
hisobla(5);ReferenceError: hisobla is not defined5.2 Nega bu foydali?
Birinchi foyda — ishonchli rekursiya. Funksiya o'zini tashqi o'zgaruvchi orqali chaqirsa, o'sha o'zgaruvchi o'zgarganda rekursiya buziladi:
let fakt = function (n) {
return n <= 1 ? 1 : n * fakt(n - 1);
};
const nusxa = fakt;
fakt = null; // tashqi nom o'zgardi
nusxa(5);TypeError: fakt is not a functionnusxa(5) ichkarida fakt(4) ni chaqirmoqchi bo'ldi, lekin fakt endi null. Nomli ifodada funksiya o'zini ichki nomi bilan chaqiradi. Tashqarida nima bo'lishidan qat'i nazar, bu nom doim o'sha funksiyani ko'rsatadi.
Ikkinchi foyda — o'qiladigan xato xabarlari. Nomli IIFE, masalan (function sozlamalarniYukla() { ... })();, DevTools'da (anonymous) emas, o'z nomi bilan ko'rinadi.
Tekshirib ko'ring:
const a = function b() {};qatoridan keyina.namenimaga teng? Tashqaridab()deb chaqirsa bo'ladimi?
Javob
a.name — "b", chunki funksiyaning o'z nomi o'zgaruvchi nomidan ustun. b() ni tashqarida chaqirib bo'lmaydi — ReferenceError: b is not defined chiqadi. b nomi faqat funksiya tanasi ichida mavjud.
6. Ko'p uchraydigan xatolar
6.1 IIFE'ni qavssiz yozish
function () { ... }(); → SyntaxError: Function statements require a function name. Nomli e'londa esa boshqa xabar chiqadi:
function salom() {
console.log("Salom!");
}();SyntaxError: Unexpected token ')'Ikkala holatda ham sabab bitta: satr boshidagi function e'lon deb o'qildi. Tuzatish: funksiyani qavsga oling — (function () { ... })();.
6.2 Oldingi qatorda nuqta-vergul yo'q
Bu xato tajribali dasturchilarni ham chalg'itadi:
const ism = "Ali"
(function () {
console.log("IIFE ishladi");
})();TypeError: "Ali" is not a functionBirinchi qator oxirida ; yo'q. JavaScript ikki qatorni bitta deb o'qidi: "Ali"(function () {...}). Ya'ni "Ali" satrini funksiya kabi chaqirmoqchi bo'ldi. Tuzatish: oldingi qatorga ; qo'ying. Shu sababli eski kodda ba'zan ;(function () { ... })(); — boshida nuqta-vergulli yozuvni ko'rasiz.
6.3 name ni o'zgartirishga urinish
function salom() {}
salom.name = "xayr";Konsolda xato: TypeError: Cannot assign to read only property 'name' of function 'function salom() {}' — "faqat o'qish uchun bo'lgan name xususiyatiga qiymat yozib bo'lmaydi".
name va length — faqat o'qish uchun (read only). Modul fayllarida bu xato beradi, oddiy <script> da esa o'zgartirish jimgina e'tiborsiz qoldiriladi. Ikkala holatda ham nom o'zgarmaydi. O'zingiz qo'shadigan xususiyatlarga boshqa nom tanlang.
6.4 length argumentlar sonini beradi deb o'ylash
fn.length — e'londagi parametrlar soni. Chaqiruvda nechta argument berilganiga u qaramaydi. Default qiymatli parametr va undan keyingilarni esa umuman sanamaydi.
7. Mashqlar
1-mashq (oson): Salomlashuvchi IIFE
Ikki IIFE yozing:
- Oddiy IIFE — konsolga
IlmHamroh ishga tushdideb chiqarsin. - Arrow IIFE —
ismparametrini olsin vaXush kelibsiz, Aziz!deb chiqarsin. Argumentni"Aziz"qilib bering.
Yechim
(function () {
console.log("IlmHamroh ishga tushdi");
})();
((ism) => {
console.log(`Xush kelibsiz, ${ism}!`);
})("Aziz");Konsolda:
IlmHamroh ishga tushdi
Xush kelibsiz, Aziz!Ikkinchi IIFE'da argument oxirgi qavs ichida: ("Aziz"). Birinchi IIFE oxiridagi ; muhim — busiz ikkinchi IIFE'ning qavsi birinchisining natijasini chaqirishga urinardi.
2-mashq (o'rta): Nom va parametrlar
Quyidagi uch funksiyani yozing. Har biri uchun name va length ni bitta qatorda chiqaring. Avval javobni o'zingiz taxmin qiling, keyin tekshiring.
function buyurtma(taom, soni = 1) {}
const yetkazish = (manzil, vaqt) => {};
const tolov = function payme(summa) {};Yechim
function buyurtma(taom, soni = 1) {}
const yetkazish = (manzil, vaqt) => {};
const tolov = function payme(summa) {};
console.log(buyurtma.name, buyurtma.length);
console.log(yetkazish.name, yetkazish.length);
console.log(tolov.name, tolov.length);Konsolda:
buyurtma 1
yetkazish 2
payme 1buyurtma da soni default qiymatli — shuning uchun length 1. tolov ning nomi payme, chunki funksiyaning o'z nomi o'zgaruvchi nomidan ustun turadi.
3-mashq (qiyin): Taksi hisoblagichi
taksi(masofa) funksiyasini yozing:
- Safar narxi:
5000 + masofa * 2000so'm. - Har chaqiruvda funksiyaning
safarlarxususiyati 1 ga,tushumxususiyati esa safar narxiga oshsin. - Har safar konsolga
Safar: 3 km — 11000 so'mko'rinishida yozsin.
Keyin 3, 8 va 1 km lik safarlarni chaqiring. Oxirida Jami: 3 safar, 39000 so'm chiqsin.
Yechim
function taksi(masofa) {
const narx = 5000 + masofa * 2000;
taksi.safarlar++;
taksi.tushum += narx;
console.log(`Safar: ${masofa} km — ${narx} so'm`);
}
taksi.safarlar = 0;
taksi.tushum = 0;
taksi(3);
taksi(8);
taksi(1);
console.log(`Jami: ${taksi.safarlar} safar, ${taksi.tushum} so'm`);Konsolda:
Safar: 3 km — 11000 so'm
Safar: 8 km — 21000 so'm
Safar: 1 km — 7000 so'm
Jami: 3 safar, 39000 so'mXususiyatlar funksiya birinchi marta chaqirilishidan oldin 0 ga tenglashtirilishi shart. Aks holda taksi.safarlar++ undefined ga 1 qo'shib, NaN hosil qiladi.
8. Real ishda
- Sayt statistikasi: Yandex Metrika yoki Google Tag Manager saytga qo'shish uchun beradigan kod IIFE ichiga o'ralgan. Shunda ularning o'zgaruvchilari sizning kodingizga aralashmaydi.
- Bundler'lar: esbuild, Rollup kabi vositalar kodni brauzer uchun yig'ganda IIFE formatida chiqarishi mumkin (
format: "iife"). - Eski kod: jQuery plaginlari va 2015-yilgacha yozilgan loyihalar IIFE'ga to'la. Ularni o'qiy olish ish joyida kerak bo'ladi.
- Xatolarni qidirish:
fn.namexato xabarlarida va loglarda ko'rinadi. Funksiyalarga aniq nom bering — keyinroq o'zingizga oson bo'ladi. - Intervyu: "IIFE nima va nega ishlatilgan?", "Funksiya JavaScript'da obyektmi?" — boshlang'ich darajadagi klassik savollar.
Xulosa
- IIFE —
(function () { ... })();— yozilgan zahoti bir marta ishlaydigan funksiya. - Tashqi qavs
functionso'zini e'lon emas, ifoda qiladi — shuning uchun uni darhol chaqirsa bo'ladi. - IIFE ichidagi o'zgaruvchilar tashqariga chiqmaydi; bugun bu ishni ko'pincha blok va modullar bajaradi.
- Funksiya — maxsus obyekt:
name(nomi) valength(default'gacha parametrlar soni) xususiyatlari bor. - Funksiyaga o'z xususiyatingizni qo'sha olasiz:
taksi.safarlar = 0. - Nomli funksiya ifodasining nomi faqat ichkarida ko'rinadi va rekursiyani ishonchli qiladi.
Keyingi dars: DevTools bilan debug qilish — kodni to'xtatib, qadamma-qadam bajarib, xatoni aniq topishni o'rganamiz.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!