Mundarija (32)
- Bu darsda
- 1. Nega bu kerak?
- 2. Getter: o'qilganda hisoblanadigan xususiyat
- 2.1 Birinchi getter
- 2.2 Getter qachon ishlaydi?
- 2.3 Konsolda getter qanday ko'rinadi
- 3. Getter'ga yozib bo'ladimi?
- 4. Setter: yozilganda ishlaydigan funksiya
- 4.1 Qiymatni tekshirish
- 4.2 _narx: nega ikkita nom?
- 4.3 Juft getter/setter: toliqIsm
- 4.4 Setter qiymatni tartibga keltiradi
- 5. Getter va setter tuzoqlari
- 5.1 Setter ichida o'zining nomi
- 5.2 Spread nusxasida getter "qotadi"
- 5.3 Getter "jim" bo'lsin
- 5.4 Getter ro'yxatlarda ham chaqiriladi
- 6. Getter yoki metod?
- 7. Ko'p uchraydigan xatolar
- 7.1 Getter'ni qavs bilan chaqirish
- 7.2 Getter'da return yo'q
- 7.3 Setter o'z nomiga yozadi
- 7.4 Getter'ga yozish
- 7.5 Spread getter'ni "qotiradi"
- 8. Mashqlar
- 1-mashq (oson): yorliq getter'ga
- 2-mashq (o'rta): Bron uchun odam soni
- 3-mashq (qiyin): Chegirmali savat
- 4-mashq: Vazifalar qadami — holat.qoldi getter
- 9. Real ishda
- Xulosa
- Manbalar
JavaScript getter va setter: get va set bilan hisoblanadigan va tekshiriladigan xususiyatlar
Qisqacha: Getter — o'qilganda ishlaydigan funksiya:
get jami() { ... }deb yoziladi vasavat.jamideb, qavssiz o'qiladi. Setter — yozilganda ishlaydigan funksiya:set narx(qiymat) { ... }—taom.narx = 35000uni chaqiradi. Getter har doim yangi hisoblangan qiymatni beradi, setter esa noto'g'ri qiymatni obyektga kiritmaydi.
Bu darsda
getbilan hisoblanadigan xususiyat yasay olasiz va u nega eskirib qolmasligini tushuntira olasiz.setbilan yozilayotgan qiymatni tekshira olasiz._narxkabi pastki chiziqli nomlar nimani bildirishini va nimani bildirmasligini bilasiz.- Getter'ga yozish, cheksiz rekursiya va spread nusxasidagi tuzoqlarni taniysiz.
vazifalardagiholatgaqoldigetter'ini qo'shasiz — u sonnistatistika()dan oladi.
Oldin bilishingiz kerak: Shorthand, computed kalitlar va metodlar (metod va this), Sayoz va chuqur nusxalash, reduce, Holatdan UI chizish.
1. Nega bu kerak?
«Bahor»da Otabek buyurtma qabul qiladi. Savat obyektida taomlar ro'yxati va jami summa saqlanadi:
const savat = {
taomlar: [{ nom: "Osh", narx: 35000 }],
jami: 35000,
};
savat.taomlar.push({ nom: "Ko'k choy", narx: 5000 });
console.log(savat.taomlar.length); // 2
console.log(savat.jami); // 35000Ko'k choy qo'shildi, jami esa hamon 35 000. Kimdir push dan keyin jami ni yangilashni unutdi. Bunday xato juda keng tarqalgan: bitta ma'lumot ikki joyda saqlansa, ertami-kechmi ular bir-biridan farq qilib qoladi. Mijoz 40 000 lik ovqat yeb, 35 000 to'lab ketadi.
Bu xatoni 09-qismda boshqa ko'rinishda ham uchratgan edik. Holatdan UI chizish darsida qoida bor edi: ma'lumot faqat bitta joyda — holat da — saqlanadi, ekran esa undan har safar chiziladi. Ekrandagi son va holat dagi son ikki xil bo'lib qolmasligi uchun. Obyekt ichida ham xuddi shu qoida ishlaydi: bir ma'lumotdan kelib chiqadigan narsa alohida saqlanmasin.
To'g'ri yechim — jami ni umuman saqlamaslik. Uni har safar taomlardan hisoblash kerak. Shorthand va metodlar darsida buning bir usulini ko'rgan edik — metod: savat.jamiHisobla(). Lekin o'sha darsda yana bir imkoniyatni va'da qilgan edik: qavssiz o'qiladigan, lekin ortida funksiya ishlaydigan xususiyat — getter. Bugun shu va'dani bajaramiz.
Hayotdan o'xshatish: taksidagi taksometr. Ekranda "Summa: 18 000" turibdi. Haydovchi bu sonni qo'lda yozib bormaydi — ekran har lahzada masofa va vaqtdan hisoblab ko'rsatadi. Siz shunchaki ekranga qaraysiz. Getter — o'sha ekran: siz savat.jami ga "qaraysiz", JavaScript esa uni o'sha lahzada hisoblaydi.
2. Getter: o'qilganda hisoblanadigan xususiyat
2.1 Birinchi getter
const savat = {
taomlar: [{ nom: "Osh", narx: 35000 }],
get jami() {
return this.taomlar.reduce((s, t) => s + t.narx, 0);
},
};
console.log(savat.jami); // 35000
savat.taomlar.push({ nom: "Ko'k choy", narx: 5000 });
console.log(savat.jami); // 40000get jami() { ... } — metodga o'xshaydi, faqat oldida get so'zi turibdi. O'qilishi esa xususiyatdek: savat.jami, qavssiz. push dan keyin hech kim hech narsani yangilamadi, lekin jami to'g'ri chiqdi — chunki u o'qilgan paytda hisoblandi.
Ichidagi this — Metodlar darsidagi qoida: savat.jami o'qilganda nuqtadan oldin savat turibdi, demak this — savat.
Getter (getter) — xususiyat o'qilganda avtomatik chaqiriladigan funksiya. Uning qaytargan qiymati — xususiyatning qiymati. Inglizcha "get" — "olmoq".
Hisoblanadigan xususiyat (computed property) — qiymati saqlanmaydigan, boshqa ma'lumotlardan har safar hisoblanadigan xususiyat. Getter — uni yasash usuli.
Diqqat: "Computed" so'zi Computed kalitlar darsida ham uchragan edi:
{ [kalit]: qiymat }— kalit nomi o'zgaruvchidan olinadi. Bu boshqa narsa. Bugungi "hisoblanadigan xususiyat" — kalit nomi oddiy, uning qiymati har safar hisoblanadi.
2.2 Getter qachon ishlaydi?
Getter ichiga console.log qo'yib, uning qachon chaqirilishini kuzatamiz. Keyingi tugmasini bosing va konsolga qarang — getter ichidagi qator har o'qishda chiqadi:
Ikki o'qish — ikki marta "hisoblanyapti...". Getter natijani eslab qolmaydi. Bu uning kuchi ham (qiymat doim yangi), zaif tomoni ham (har o'qishda hisob). Bu haqda «Getter yoki metod?» bo'limida gaplashamiz.
2.3 Konsolda getter qanday ko'rinadi
const savat = {
taomlar: [{ nom: "Osh", narx: 35000 }],
get jami() {
return this.taomlar.reduce((s, t) => s + t.narx, 0);
},
};
console.log(savat);Konsolda:
{ taomlar: [ { nom: 'Osh', narx: 35000 } ], jami: [Getter] }Node qiymat o'rniga [Getter] deb yozdi. U getter'ni o'zi chaqirmaydi — getter ichida biror ish (masalan, konsolga yozish) bo'lsa, oddiy console.log uni tasodifan ishga tushirmasin. Chrome konsoli esa jami: (...) ko'rsatadi; uch nuqtani bossangiz, getter chaqiriladi va qiymat chiqadi.
Tekshirib ko'ring:
const k = { a: 2, get b() { return this.a * 10; } }; k.a = 5;—k.bnima qaytaradi?k.b()chi?
Javob
k.b — 50: getter o'qilgan paytdagi a (5) bilan hisobladi. k.b() esa TypeError: k.b is not a function. k.b o'qilganda getter ishlab, son qaytardi — 50. Keyin 50() ni chaqirishga urinildi. Getter'ni qavs bilan chaqirmaysiz — uni o'qiysiz.
3. Getter'ga yozib bo'ladimi?
Faqat get yozilgan xususiyatga qiymat bersak nima bo'ladi? Javob — skript turiga bog'liq. Avval modul faylda (.mjs, type="module"):
const savat = {
taomlar: [35000],
get jami() {
return this.taomlar.reduce((s, n) => s + n, 0);
},
};
savat.jami = 0;TypeError: Cannot set property jami of #<Object> which has only a getterTarjimasi: "faqat getter'i bor obyektning jami xususiyatiga qiymat berib bo'lmaydi". #<Object> — Node shunday "qandaydir obyekt" deydi. Getter — hisoblanadigan qiymat, uni "qo'lda" o'zgartirib bo'lmaydi.
Oddiy <script> yoki .cjs faylda esa xato chiqmaydi — yozish shunchaki jimgina e'tiborsiz qoladi:
const savat = {
taomlar: [35000],
get jami() {
return this.taomlar.reduce((s, n) => s + n, 0);
},
};
savat.jami = 0;
console.log(savat.jami); // 35000= 0 hech narsa qilmadi, xato ham bermadi. Bu — ikki xil JavaScript "rejimi"ning farqi: modullar qat'iy rejimda ishlaydi va jim xatolarni haqiqiy xatoga aylantiradi. Shu sahifadagi «Ishga tushir» tugmasi ham kodni qat'iy rejimda bajaradi, ikkinchi blokni esa oddiy skript sifatida. Ikkalasini bosib solishtiring: birinchisida xato chiqadi, ikkinchisida — 35000. Bu farqni Strict mode darsida to'liq ochamiz. Hozircha eslab qoling: getter'ga yozish — doim xato, faqat ba'zan ko'rinmaydigan xato. 09-qismdagi vazifalar.js — oddiy <script defer>, demak u yerda bunday xato jim o'tadi.
4. Setter: yozilganda ishlaydigan funksiya
4.1 Qiymatni tekshirish
Menyuda narx noto'g'ri kiritilishi mumkin: manfiy son, nol, satr. Oddiy xususiyat hammasini qabul qiladi. Setter esa yozishdan oldin tekshira oladi:
const taom = {
nom: "Osh",
_narx: 35000,
get narx() {
return this._narx;
},
set narx(qiymat) {
if (!Number.isInteger(qiymat) || qiymat <= 0) {
console.warn(`Noto'g'ri narx: ${qiymat}`);
return;
}
this._narx = qiymat;
},
};
taom.narx = -5000;
taom.narx = "arzon";
taom.narx = 38000;
console.log(taom.narx);Konsolda:
Noto'g'ri narx: -5000
Noto'g'ri narx: arzon
38000taom.narx = -5000 — oddiy tayinlashga o'xshaydi. Lekin narx da setter bor, shuning uchun JavaScript set narx(-5000) ni chaqirdi. Setter tekshirdi, rad etdi va qiymatni saqlamadi. Uchinchi tayinlash tekshiruvdan o'tdi va _narx ga yozildi. (38 000 — misol uchun; kanonik menyuda osh 35 000.)
Setter (setter) — xususiyatga qiymat berilganda avtomatik chaqiriladigan funksiya. Berilgan qiymat unga yagona argument bo'lib keladi. Inglizcha "set" — "o'rnatmoq".
Hayotdan o'xshatish: bankomat. Siz "pul qo'yish" tugmasini bosasiz — lekin pul to'g'ridan-to'g'ri hisobga tushmaydi. Avval mashina har bir kupyurani tekshiradi: soxta yoki yirtiq bo'lsa — qaytaradi. Setter — o'sha tekshiruvchi mexanizm.
Number.isInteger — Matn ↔ son darsidan: "bu butun sonmi?". Satr yoki kasr kelsa — false.
4.2 _narx: nega ikkita nom?
Qiymat qayerdadir saqlanishi kerak. narx nomini getter va setter egallagan, shuning uchun haqiqiy qiymat boshqa nomda turadi — _narx.
Pastki chiziq (_) — dasturchilar orasidagi kelishuv: "bu ichki xususiyat, unga tashqaridan to'g'ridan-to'g'ri tegmang, narx orqali ishlang". Callback imzosi darsidagi _ parametri kabi — JavaScript qoidasi emas, odamlar uchun belgi.
Muhim: _ himoya qilmaydi. Kim xohlasa, setter'ni chetlab o'tadi:
const taom = {
_narx: 35000,
get narx() {
return this._narx;
},
set narx(qiymat) {
if (qiymat > 0) {
this._narx = qiymat;
}
},
};
taom._narx = -1;
console.log(taom.narx); // -1Tekshiruv ishlamadi — chunki biz setter'ga emas, to'g'ridan-to'g'ri _narx ga yozdik. _ — "iltimos, tegmang" yozuvi, qulf emas. Haqiqiy, tashqaridan ko'rinmaydigan xususiyatlar ham bor — #narx, ularni Private # maydonlar darsida o'rganamiz.
4.3 Juft getter/setter: toliqIsm
Getter va setter birga ishlaganda bitta xususiyat ikki tomonlama "tarjimon" bo'ladi. Bron obyektida mehmonning ismi va familiyasi alohida saqlanadi, lekin forma bitta "To'liq ism" maydonidan keladi:
const bron = {
ism: "",
familiya: "",
get toliqIsm() {
return `${this.ism} ${this.familiya}`;
},
set toliqIsm(matn) {
const [ism, familiya = ""] = matn.trim().split(" ");
this.ism = ism;
this.familiya = familiya;
},
};
bron.toliqIsm = " Malika Karimova ";
console.log(bron.ism); // Malika
console.log(bron.familiya); // Karimova
console.log(bron.toliqIsm); // Malika Karimova
console.log(bron);Konsolda:
Malika
Karimova
Malika Karimova
{ ism: 'Malika', familiya: 'Karimova', toliqIsm: [Getter/Setter] }Setter satrni tozaladi (trim), bo'ldi (split) va destructuring bilan ikki o'zgaruvchiga ajratdi. familiya = "" — default qiymat: familiya yozilmasa, undefined o'rniga bo'sh satr. Getter esa teskari ishni qiladi. Node bunday xususiyatni [Getter/Setter] deb ko'rsatadi.
Faqat set yozilgan xususiyatni o'qisangiz — undefined keladi. Bunday "faqat yoziladigan" xususiyat juda kam kerak bo'ladi.
Tekshirib ko'ring: Yuqoridagi
brondabron.toliqIsm = "Bobur"dan keyinbron.toliqIsmnima qaytaradi? Oxirida nima bor?
Javob
"Bobur " — oxirida bo'sh joy. split(" ") bitta elementli massiv berdi, familiya default "" oldi. Getter esa ${ism} ${familiya} ni yopishtirdi — o'rtadagi bo'sh joy qoldi. Tuzatish: getter'da .trim() qo'shing — shablon satr oxiriga .trim() yoziladi va chetdagi bo'sh joy olib tashlanadi.
4.4 Setter qiymatni tartibga keltiradi
Setter faqat "ha" yoki "yo'q" demaydi — qiymatni saqlashdan oldin uni bir xil ko'rinishga keltirishi ham mumkin. Bron formasida mehmonlar telefonni har xil yozadi: +998 90 000 00 00, +998 90 000-00-00, +99890 0000000. Bazada esa bitta shakl kerak — aks holda bitta mehmon uch xil "mehmon" bo'lib qoladi va qidiruv ishlamaydi.
const mehmon = {
_telefon: "",
get telefon() {
return this._telefon;
},
set telefon(matn) {
this._telefon = matn.replaceAll(" ", "").replaceAll("-", "");
},
};
mehmon.telefon = "+998 90 000-00-00";
console.log(mehmon.telefon); // +998900000000
mehmon.telefon = "+99890 0000000";
console.log(mehmon.telefon); // +998900000000Ikki xil yozuv — bitta saqlangan shakl. replaceAll — Matnni o'zgartirish va tozalash darsidan. Kodning qolgan qismi endi "telefon qanday yozilgan bo'lishi mumkin?" deb o'ylamaydi: mehmon.telefon doim toza. Tozalash qoidasi bitta joyda — setter ichida. Qoida o'zgarsa (masalan, qavslarni ham olib tashlash kerak bo'lsa), faqat shu yerni tuzatasiz.
Bu — setter'ning ikkinchi asosiy vazifasi. Birinchisi — noto'g'ri qiymatni rad etish (narx), ikkinchisi — to'g'ri, lekin "tartibsiz" qiymatni bir shaklga keltirish (telefon). Ko'pincha ikkalasi birga ishlaydi: avval tozalanadi, keyin tekshiriladi.
Tekshirib ko'ring:
mehmonga telefonni tekshiruv bilan qo'shmoqchimiz: tozalangan raqam+998bilan boshlanib, aynan 13 belgi bo'lsin. Tekshiruv tozalashdan oldin turishi kerakmi yoki keyin?
Javob
Keyin. "+998 90 000-00-00" tozalanmasdan oldin 17 belgi — u to'g'ri raqam bo'lsa ham rad etilardi. Avval replaceAll bilan bir shaklga keltiramiz, keyin startsWith("+998") va length === 13 ni tekshiramiz (Matn ichida qidirish). Qoida: "tozala, keyin tekshir" — formalarda ham shunday (input va change).
5. Getter va setter tuzoqlari
5.1 Setter ichida o'zining nomi
Eng ko'p uchraydigan xato — setter ichida xuddi shu nomga yozish:
const taom = {
set narx(qiymat) {
this.narx = qiymat;
},
};
taom.narx = 35000;RangeError: Maximum call stack size exceededTarjimasi: "chaqiruvlar stekining eng katta o'lchami oshib ketdi". this.narx = qiymat — bu ham narx ga yozish, demak u yana setter'ni chaqiradi. U yana this.narx = ... qiladi, u yana setter'ni... Rekursiya darsidagi to'xtash sharti yo'q rekursiyaning o'zi. Ming-minglab chaqiruvdan keyin stek to'ladi va JavaScript to'xtaydi.
_narx aynan shu sababdan kerak: setter boshqa nomga yozadi. Getter'da ham xuddi shunday: get narx() { return this.narx; } — yana cheksiz chaqiruv.
5.2 Spread nusxasida getter "qotadi"
Sayoz va chuqur nusxalash darsidagi spread getter'ni nusxalamaydi — u getter'ni chaqiradi va natijasini oddiy qiymat sifatida yozadi:
const savat = {
taomlar: [35000],
get jami() {
return this.taomlar.reduce((s, n) => s + n, 0);
},
};
const nusxa = { ...savat };
nusxa.taomlar.push(5000);
console.log(savat.jami); // 40000
console.log(nusxa.jami); // 35000
console.log(nusxa);Konsolda:
40000
35000
{ taomlar: [ 35000, 5000 ], jami: 35000 }Nusxada jami endi oddiy son — 35 000. Taomlar ro'yxati umumiy (sayoz nusxa!), shuning uchun ikkalasida ham ikki taom. Lekin nusxa.jami hisoblanmaydi — u nusxalangan lahzadagi qiymatda qotib qoldi. «Nega bu kerak?» bo'limidagi eskirgan jami xatosi qaytdi. structuredClone ham xuddi shunday qiladi.
Getter'ni nusxalashning yo'li bor — buning uchun xususiyatning "yashirin sozlamalari"ni bilish kerak. Keyingi dars — Xususiyat deskriptorlari — aynan shu haqida.
5.3 Getter "jim" bo'lsin
Getter'ni o'qigan odam "men shunchaki qiymatni ko'ryapman" deb o'ylaydi. Shuning uchun getter:
- Hech narsani o'zgartirmasin. Har o'qishda hisoblagichni oshiradigan, ro'yxatdan element olib tashlaydigan getter — juda chalkash xatolar manbai. Getter — toza funksiya bo'lsin.
- Tez ishlasin.
savat.jamini o'qigan odam u bir soniya kutishini kutmaydi. Og'ir hisob kerak bo'lsa — metod yozing, nomi esa buni aytsin:hisobotTayyorla().
5.4 Getter ro'yxatlarda ham chaqiriladi
Getter — obyektning to'laqonli xususiyati. Shuning uchun u Obyekt bo'ylab yurish darsidagi vositalarda ham ko'rinadi:
const savat = {
taomlar: [35000, 5000],
get jami() {
return this.taomlar.reduce((s, n) => s + n, 0);
},
};
console.log(Object.keys(savat)); // [ 'taomlar', 'jami' ]
console.log(Object.entries(savat).at(-1)); // [ 'jami', 40000 ]Object.keys getter nomini berdi. Object.entries esa qiymatlarni yig'ish uchun getter'ni chaqirdi — 40000 hisoblangan qiymat. Ko'pincha bu yaxshi. Lekin ba'zan halaqit beradi: masalan, savatni "ma'lumot sifatida" saqlamoqchi yoki solishtirmoqchi bo'lsangiz, jami ma'lumot emas — u taomlar dan kelib chiqadi. Getter'ni bunday ro'yxatlardan yashirish usulini keyingi darsda ko'ramiz — u ham, «Spread nusxasida getter "qotadi"» bo'limidagi muammo ham bitta vosita bilan hal bo'ladi.
Tekshirib ko'ring: «Spread nusxasida getter "qotadi"» bo'limidagi
savatdanconst n = { ...savat };yasaldi. Keyinsavat.taomlar.push(1000). Endin.jamivan.taomlar.lengthnima?
Javob
n.jami — 35000, o'zgarmadi: nusxada u oddiy son, getter emas. n.taomlar.length esa — 2: spread sayoz nusxa, taomlar massivi ikkala obyektda bitta. Natijada nusxa o'ziga zid bo'lib qoldi — ikki taom, lekin jami bitta taomniki.
6. Getter yoki metod?
Bir xil ishni ikki usulda yozish mumkin: savat.jami (getter) yoki savat.jamiHisobla() (metod). Qaysi birini tanlash kerak?
| Savol | Getter | Metod |
|---|---|---|
| Argument kerakmi? | yo'q | ha bo'lishi mumkin |
| Biror narsani o'zgartiradimi? | yo'q | bo'lishi mumkin |
| Tezmi? | ha | og'ir bo'lishi mumkin |
| Nomi | ot yoki sifat: jami, toliqIsm |
fe'l: jamiHisobla, chekChiqar |
Qoida: agar narsa obyektning xususiyati kabi tuyulsa — "savatning jami", "mehmonning to'liq ismi" — va uni hisoblash arzon bo'lsa — getter. Agar u harakat bo'lsa yoki parametr kerak bo'lsa — metod. Nomlash qoidasi Funksiya e'lon qilish darsidagidek: harakat — fe'l, qiymat — natija nomi.
Tekshirib ko'ring: Quyidagilardan qaysi biri getter bo'lishi kerak:
chegirmaQol(foiz),bosmi(savat bo'shmi?),chekniChopEt()?
Javob
Faqat bosmi: argument yo'q, hech narsa o'zgarmaydi, hisob arzon (this.taomlar.length === 0). Nomi ham savol shaklida — predikat, -mi bilan. chegirmaQol(foiz) argument oladi va savatni o'zgartiradi, chekniChopEt() — harakat (yon ta'sir). Ikkalasi metod.
7. Ko'p uchraydigan xatolar
7.1 Getter'ni qavs bilan chaqirish
savat.jami() — TypeError: savat.jami is not a function. Getter allaqachon qiymat qaytardi, son esa chaqirilmaydi. Tuzatish: savat.jami.
7.2 Getter'da return yo'q
const savat = {
taomlar: [35000, 5000],
get jami() {
this.taomlar.reduce((s, n) => s + n, 0);
},
};
console.log(savat.jami); // undefinedGetter ishladi, hisobladi, lekin natijani qaytarmadi. Tuzatish: return this.taomlar.reduce(...).
7.3 Setter o'z nomiga yozadi
RangeError: Maximum call stack size exceeded. Tuzatish: qiymatni boshqa nomda saqlang — this._narx = qiymat.
7.4 Getter'ga yozish
Modulda — TypeError: Cannot set property ... which has only a getter, oddiy skriptda — jim e'tiborsiz. Tuzatish: yozish kerak bo'lsa, setter qo'shing; yozish ma'nosiz bo'lsa (hisoblanadigan qiymat), yozmang.
7.5 Spread getter'ni "qotiradi"
{ ...obyekt } getter natijasini oddiy qiymat qilib ko'chiradi. Tuzatish: hisoblanadigan qiymatni nusxalamang — kerak bo'lganda asl obyektdan o'qing.
8. Mashqlar
1-mashq (oson): yorliq getter'ga
Shorthand va metodlar darsidagi yorliq() metodini getter'ga aylantiring va qavssiz o'qing. Ishora: get so'zini qo'shing, chaqiruvdagi qavslarni olib tashlang.
const buyurtma = {
mijoz: { ism: "Dilnoza" },
manzil: { shahar: "Samarqand", tuman: "Urgut" },
yorliq() {
const m = this.manzil;
return `${this.mijoz.ism}: ${m.shahar}, ${m.tuman}`;
},
};Yechim
const buyurtma = {
mijoz: { ism: "Dilnoza" },
manzil: { shahar: "Samarqand", tuman: "Urgut" },
get yorliq() {
const m = this.manzil;
return `${this.mijoz.ism}: ${m.shahar}, ${m.tuman}`;
},
};
console.log(buyurtma.yorliq); // Dilnoza: Samarqand, Urgut
buyurtma.manzil.tuman = "Kattaqo'rg'on";
console.log(buyurtma.yorliq); // Dilnoza: Samarqand, Kattaqo'rg'onTanasi o'zgarmadi — faqat get qo'shildi. Manzil o'zgarganda yorliq ham o'zi yangilandi. yorliq — ot, harakat emas, va hisob arzon: getter uchun to'g'ri nomzod.
2-mashq (o'rta): Bron uchun odam soni
«Bahor»da bitta bronga 1 dan 20 gacha odam yoziladi. bron obyektiga odam setter'ini yozing: butun son va 1–20 oralig'ida bo'lmasa — console.warn bilan rad etsin. Getter _odam ni qaytarsin. Qo'shimcha getter stollar — nechta to'rt kishilik stol kerak (Math.ceil, Math obyekti).
Yechim
const bron = {
_odam: 1,
get odam() {
return this._odam;
},
set odam(soni) {
if (!Number.isInteger(soni) || soni < 1 || soni > 20) {
console.warn(`Odam soni 1–20 bo'lishi kerak: ${soni}`);
return;
}
this._odam = soni;
},
get stollar() {
return Math.ceil(this._odam / 4);
},
};
bron.odam = 25;
bron.odam = 2.5;
bron.odam = 9;
console.log(bron.odam, bron.stollar);Konsolda:
Odam soni 1–20 bo'lishi kerak: 25
Odam soni 1–20 bo'lishi kerak: 2.5
9 3stollar — faqat getter: uni o'zgartirish ma'nosiz, u odam dan kelib chiqadi. Tekshiruv bron formasidagi max="20" bilan bir xil qoida — brauzer formani tekshiradi, setter esa ma'lumotni dastur ichida ham himoyalaydi.
3-mashq (qiyin): Chegirmali savat
savat obyektini yozing:
taomlar—{ nom, narx }massivi;chegirma— foiz, setter orqali; faqat 0–50 oralig'idagi butun son qabul qilinsin;jami— getter: narxlar yig'indisi, chegirma ayirilgan, butun so'mga yaxlitlangan;bosmi— getter: savatda taom yo'qmi.
Ishora: yaxlitlash — Math.round; foizni ayirish — summa * (100 - foiz) / 100. Pulni butun so'mda saqlash — Pul va aniq hisob-kitob.
Yechim
const savat = {
taomlar: [],
_chegirma: 0,
get chegirma() {
return this._chegirma;
},
set chegirma(foiz) {
if (!Number.isInteger(foiz) || foiz < 0 || foiz > 50) {
console.warn(`Chegirma 0–50% bo'lishi kerak: ${foiz}`);
return;
}
this._chegirma = foiz;
},
get jami() {
const summa = this.taomlar.reduce((s, t) => s + t.narx, 0);
return Math.round((summa * (100 - this._chegirma)) / 100);
},
get bosmi() {
return this.taomlar.length === 0;
},
};
console.log(savat.bosmi, savat.jami);
savat.taomlar.push({ nom: "Osh", narx: 35000 });
savat.taomlar.push({ nom: "Lag'mon", narx: 28000 });
savat.chegirma = 70;
savat.chegirma = 15;
console.log(savat.bosmi, savat.jami);Konsolda:
true 0
Chegirma 0–50% bo'lishi kerak: 70
false 5355063 000 dan 15% — 53 550. jami ikki narsaga tayanadi — taomlar va _chegirma — va ulardan birortasi o'zgarsa, keyingi o'qishda to'g'ri natija beradi. Hech qayerda "jamini yangila" degan qator yo'q. Bo'sh savatda reduce ning boshlang'ich 0 i ishladi (reduce).
4-mashq: Vazifalar qadami — holat.qoldi getter
10-qismning obyektlar moduli boshlanadi. vazifalar da yangi branch oching: git switch -c refactor/obyektlar. Bu va keyingi to'rt darsda — xulq o'zgarmaydi, kod yaxshilanadi; branch'ni modul oxirida, Ichma-ich ma'lumotni immutable yangilash darsida main ga qo'shamiz.
Hozir vazifalar.js da hisob statistika() funksiyasidan olinadi (Guruhlash darsidan):
function statistika() {
const guruhlar = Object.groupBy(holat.vazifalar, guruhNomi);
return {
qoldi: guruhlar.faol?.length ?? 0,
bajarildi: guruhlar.bajarilgan?.length ?? 0,
};
}render() ga ikkala son bir chaqiruvda kerak — u shunday qolsin. Lekin "nechta vazifa qoldi?" — ilovadagi eng ko'p beriladigan savol. Uni DevTools konsolida tekshiramiz, keyingi qadamlarda ham so'raymiz. Har safar statistika().qoldi deb yozish — funksiya chaqiruvi va ortiqcha obyekt. holat.qoldi deb o'qish tabiiyroq: bu holat ning xususiyati, u holat.vazifalar dan hisoblanadi.
Faqat uni oddiy xususiyat qilib saqlamang (qoldi: 2) — «Nega bu kerak?» bo'limidagi eskirgan jami xatosi qaytadi. holat ga qoldi getter'ini qo'shing. U sonni o'zi qayta sanamasin — statistika() dan olsin: hisob qoidasi bitta joyda qolsin. Xulq o'zgarmasin.
Yechim
holat ning oxiriga getter qo'shiladi:
const holat = {
vazifalar: [
{ id: 1, matn: "Non olish", bajarildi: false },
{ id: 2, matn: "DOM darsini takrorlash", bajarildi: true },
{ id: 3, matn: "Onamga qo'ng'iroq qilish", bajarildi: false },
],
keyingiId: 4,
filtr: "hammasi",
tahrirId: null,
get qoldi() {
return statistika().qoldi;
},
};render() va statistika() ga tegmaymiz.
Nima o'zgardi:
- Ma'lumot va undan kelib chiqadigani bir joyda.
holatendi "qanday vazifalar bor" ni ham, "nechtasi qoldi" ni ham biladi. Son esa saqlanmaydi — har o'qishda hisoblanadi, shuning uchun eskirmaydi. - Hisob qoidasi — bitta. Getter o'z
reduceini yozmadi,statistika()ga murojaat qildi. Agar getter sonni o'zi sanasa, bitta qoida ikki joyda yashardi — ertami-kechmi ular bir-biridan farq qilib qolardi. Bu — «Nega bu kerak?» dagi xatoning kod ko'rinishi. statistikapastda e'lon qilingan — muammo emas. Getterholatyaratilganda emas, o'qilganda ishlaydi. O'sha paytda butun fayl bajarilib bo'lgan.- Nomi — ot.
qoldi— "qolgan vazifalar soni". U harakat emas, shuning uchun fe'l emas; ekrandagi "2 ta vazifa qoldi" bilan bir xil so'z.
Getter statistika() bilan doim bir xil javob berishini Node'da tekshiring — har xil holatlarda:
const holat = {
vazifalar: [],
get qoldi() {
return statistika().qoldi;
},
};
function guruhNomi(vazifa) {
return vazifa.bajarildi ? "bajarilgan" : "faol";
}
function statistika() {
const guruhlar = Object.groupBy(holat.vazifalar, guruhNomi);
return {
qoldi: guruhlar.faol?.length ?? 0,
bajarildi: guruhlar.bajarilgan?.length ?? 0,
};
}
const holatlar = [
[],
[{ bajarildi: true }],
[{ bajarildi: false }, { bajarildi: true }, { bajarildi: false }],
];
for (const royxat of holatlar) {
holat.vazifalar = royxat;
console.log(statistika().qoldi, holat.qoldi);
}Konsolda:
0 0
0 0
2 2Har qatorda ikki son teng. E'tibor bering: holat.vazifalar ga yangi massiv berilganda ham getter darhol yangisini sanadi — u har o'qishda statistika() orqali holat.vazifalar ga qaytadan qaraydi.
Brauzerda butun ilovani sinab chiqing:
- Ochilganda — "2 ta vazifa qoldi, 1 ta bajarildi". DevTools konsolida
holat.qoldi—2. - Bitta vazifani belgilang — hisob "1 ta vazifa qoldi, 2 ta bajarildi", konsolda
holat.qoldi—1. Qaytaring — yana2. - Yangi vazifa qo'shing —
holat.qoldi—3. Hammasini o'chiring —0, ekranda bo'sh ro'yxat xabari. - Filtrlar, tahrirlash,
Esc,Enter— hammasi avvalgidek.
DevTools konsolida holat ni yozing: qoldi: (...) ko'rinadi — uch nuqtani bossangiz, son chiqadi.
Commit: Vazifalar: holat.qoldi getter'ini qo'sh. Branch'ni hali main ga qo'shmang.
9. Real ishda
- DOM'ning o'zi getter va setter'lardan iborat.
input.value = "",element.textContent = "...",tugma.hidden = true— bularning hammasi setter'lar. Siz oddiy tayinlash yozasiz, brauzer esa ichida sahifani qayta chizadi.royxat.children.length— getter: har o'qishda joriy bolalar soni. 09-qismdagiinnerHTMLsetter'i esa yozilgan satrni HTML sifatida tahlil qiladi (XSS xavfi shu yerdan). - Klasslar.
classichida getter va setter aynan shu sintaksis bilan yoziladi (Getter/setter vastatic). Real loyihalarda getter'larni ko'pincha klasslarda ko'rasiz. - Freymvorklar. Vue'dagi
computed, MobX va Svelte'dagi hisoblanadigan qiymatlar — g'oyasi getter'ning o'zi: "ma'lumotdan kelib chiqadigan narsani saqlamang, hisoblang". - Kod ko'rib chiqishda. Tajribali dasturchi ikki narsani darhol so'raydi: "bu getter biror narsani o'zgartiryaptimi?" va "bu qiymat nega alohida saqlanyapti — hisoblab bo'lmaydimi?". Birinchisi — yashirin yon ta'sir xavfi, ikkinchisi — eskirib qoladigan ma'lumot xavfi. Ikkala savolning javobi bugungi darsda.
- Intervyu. "Getter va oddiy metod farqi nima?", "setter ichida
this.x = vyozsa nima bo'ladi?" — ikkalasi uchraydi. Ikkinchisining javobi:RangeError— cheksiz rekursiya.
Xulosa
- Getter — o'qilganda ishlaydigan funksiya:
get jami() { ... }, o'qilishi —obyekt.jami, qavssiz. - Hisoblanadigan xususiyat saqlanmaydi, shuning uchun eskirmaydi — "bitta ma'lumot ikki joyda" xatosi yo'qoladi.
- Setter — yozilganda ishlaydigan funksiya:
set narx(qiymat) { ... }; qiymatni tekshirib, keyin saqlaydi. - Haqiqiy qiymat boshqa nomda turadi (
_narx);_— kelishuv, himoya emas. Setter o'z nomiga yozsa — cheksiz rekursiya. - Getter'ga yozish modulda
TypeError, oddiy skriptda jim; spread vastructuredClonegetter'ni oddiy qiymatga aylantiradi. - Getter — ot nomli, arzon, yon ta'sirsiz; harakat yoki argument kerak bo'lsa — metod.
Keyingi dars: Xususiyat deskriptorlari — har xususiyatning yashirin sozlamalarini (yozish, sanash, qayta sozlash ruxsatlarini) ko'ramiz va getter'ni nusxalashni o'rganamiz.
Manbalar
- MDN: "get", "set", "Working with objects" — "Defining getters and setters" — developer.mozilla.org
- ECMAScript 2025 Language Specification: "Method Definitions" (
get/set) — tc39.es/ecma262
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!