Mundarija (32)
- Bu darsda
- 1. Nega bu kerak?
- 2. Getter va setter klassda
- 2.1 Eslab olamiz: obyektdagi getter
- 2.2 # maydon + getter + setter
- 2.3 Hisoblanadigan xususiyat
- 2.4 Faqat o'qiladigan xususiyat
- 2.5 Getter va setter qayerda yashaydi?
- 2.6 Getter qachon kerak, qachon metod?
- 3. static: klassning o'z a'zolari
- 3.1 static maydon
- 3.2 static metod
- 3.3 Tanish static metodlar
- 3.4 static ichida this va private static
- 3.5 Tuzoq: static metodni callback qilib berish
- 3.6 static {} bloki
- 4. Factory metod
- 4.1 Konstruktorning cheklovi
- 4.2 Qaysi biri qachon?
- 5. Ko'p uchraydigan xatolar
- 5.1 Setter ichida o'ziga yozish
- 5.2 Maydon getterni yopib qo'yadi
- 5.3 static a'zoni nusxadan chaqirish
- 5.4 static metodni callback qilib berish
- 6. Mashqlar
- 1-mashq (oson): Bron va odam soni
- 2-mashq (o'rta): Bronlar hisoblagichi va factory
- 3-mashq (qiyin): Savat
- 4-mashq: Vazifalar qadami — Vazifa ga o'zgarmas va factory
- 7. Real ishda
- Xulosa
- Manbalar
JavaScript klassida getter, setter va static: nusxaniki va klassning o'ziniki
Qisqacha: Klassdagi
get narx()vaset narx(q)— xususiyat o'qilganda yoki yozilganda ishlaydigan funksiyalar: qiymatni hisoblaydi yoki tekshiradi, tashqaridan esa oddiyosh.narxbo'lib ko'rinadi.staticbilan yozilgan a'zo esa nusxaga emas, klassning o'ziga tegishli:Taom.dan(malumot),Array.from(...). Nusxaning ma'lumoti — oddiy a'zoda, hamma nusxa uchun umumiy narsa —staticda.
Bu darsda
- Klass ichida getter va setter yoza olasiz: hisoblanadigan xususiyat, tekshiruvli yozish va faqat o'qiladigan xususiyat.
staticmaydon va metod nima ekanini, ular qayerda yashashini tushuntira olasiz.staticmetod ichidagithisni va uning tuzog'ini bilasiz.static {}bloki va factory metod (Taom.dan(...)) ni yoza olasiz.vazifalardagiVazifaklassigastatico'zgarmas va factory metod qo'shasiz.
Oldin bilishingiz kerak: Getter va setter, class sintaksisi, Class maydonlari, Private # maydon va metodlar.
1. Nega bu kerak?
Private # maydon darsida narxni #narx ga yashirdik. Endi uni tashqaridan hech kim buzolmaydi. Lekin ikki savol ochiq qoldi.
Birinchisi: narxni o'qish va yangilash baribir kerak. Rustam aka oshning narxini 35 000 dan 38 000 ga ko'tarsa-chi? osh.narxniOzgartir(38000) kabi metod yozish mumkin. Lekin osh.narx = 38000 ancha tabiiy o'qiladi. Faqat bitta shart bilan: manfiy yoki matnli narx kirib qolmasin.
Ikkinchisi: ba'zi ma'lumot hech bir taomga tegishli emas. "Menyuda nechta taom yaratildi?", "narx qaysi valyutada?" — bu savollar oshga ham, mantiga ham emas, taomlar umumiga tegishli. Har nusxaga nusxa qilib yozish — isrof va chalkashlik.
Hayotdan o'xshatish. «Bahor» dagi har stol — alohida: birida 4 kishi, birida 2 kishi o'tiribdi. Bu — nusxaning ma'lumoti. Eshik oldidagi "Ish vaqti: 7:00–23:00" lavhasi esa bitta, choyxonaning o'ziga tegishli. Uni har stolga yopishtirmaysiz. Klassda ham shunday: stolning o'z ma'lumoti — oddiy a'zo, eshikdagi lavha — static.
Bu dars ikkala savolni yopadi. Avval getter va setter — xususiyatni "boshqariladigan" qilamiz. Keyin static — klassning o'z a'zolari. Oxirida ikkalasini birlashtiradigan naqsh — factory metod.
2. Getter va setter klassda
2.1 Eslab olamiz: obyektdagi getter
Getter va setter darsida obyekt literalida yozgan edik:
const savat = {
narxlar: [35000, 5000],
get jami() {
return this.narxlar.reduce((s, n) => s + n, 0);
},
};
console.log(savat.jami); // 40000jami — funksiya, lekin qavssiz o'qiladi. Getter (getter) — xususiyat o'qilganda chaqiriladigan funksiya. Setter (setter) — xususiyatga qiymat yozilganda chaqiriladigan funksiya. Klassda sintaksis aynan shunday, faqat vergulsiz — metodlar kabi.
2.2 # maydon + getter + setter
Eng ko'p uchraydigan shakl: qiymat private maydonda, tashqariga getter va setter orqali chiqadi.
class Taom {
#narx;
constructor(nom, narx) {
this.nom = nom;
this.narx = narx; // setter orqali o'tadi
}
get narx() {
return this.#narx;
}
set narx(yangi) {
if (!Number.isInteger(yangi) || yangi <= 0) {
console.warn(`Noto'g'ri narx: ${yangi}`);
return;
}
this.#narx = yangi;
}
}
const osh = new Taom("Osh", 35000);
osh.narx = 38000;
console.log(osh.narx);
osh.narx = -5;
osh.narx = "40 000";
console.log(osh.narx);Konsolda:
38000
Noto'g'ri narx: -5
Noto'g'ri narx: 40 000
38000Qatorma-qator:
this.narx = narx— konstruktor ham setter orqali yozadi. Shuning uchun yaratishda ham tekshiruv ishlaydi:new Taom("Osh", -1)ham ogohlantiradi.osh.narx = 38000— oddiy tayinlashga o'xshaydi, lekin aslidaset narx(38000)chaqirildi. Tekshiruvdan o'tdi va#narxga yozildi.-5va"40 000"— setter ularni rad etdi.#narxo'zgarmadi, shuning uchun oxirida yana38000.
Tashqaridan qaraganda osh.narx — oddiy xususiyat. Ichkarida esa uni qo'riqchi qo'riqlayapti. Xuddi bankomat kabi: siz "pul yechish" tugmasini bosasiz, ichkarida esa balans tekshiriladi.
Maslahat: Bu darsda noto'g'ri qiymatni
console.warnbilan bildirib, e'tiborsiz qoldiryapmiz. Real kodda setter odatda xato tashlaydi — dastur shu joyda to'xtaydi va xato aniq ko'rinadi. BunithrowvaErrorobyekti darsida o'rganamiz, hozir bilish shart emas.
2.3 Hisoblanadigan xususiyat
Getter saqlangan qiymatni qaytarishi shart emas — u hisoblab berishi mumkin. Buyurtmaning jami summasi hech qayerda saqlanmaydi: har o'qishda taomlardan yig'iladi (reduce).
class Buyurtma {
#taomlar = [];
qosh(nom, narx) {
this.#taomlar.push({ nom, narx });
}
get jami() {
return this.#taomlar.reduce((s, t) => s + t.narx, 0);
}
get soni() {
return this.#taomlar.length;
}
}
const stol4 = new Buyurtma();
stol4.qosh("Osh", 35000);
stol4.qosh("Ko'k choy", 5000);
console.log(stol4.soni, stol4.jami); // 2 40000Nega jami ni maydonda saqlab, har qosh da yangilab bormaymiz? Chunki unda ikki joyda bitta haqiqat bo'lardi: taomlar ro'yxati va alohida son. Biri yangilanib, ikkinchisi unutilsa — chek noto'g'ri chiqadi. Getter bilan haqiqat bitta: ro'yxat. Jami undan har safar to'g'ri hisoblanadi.
O'zingiz to'ldiring. Uchinchi taom qo'shilsa — stol4.qosh("Manti", 30000) — stol4.jami [:70000] bo'ladi, stol4.soni esa [:3].
2.4 Faqat o'qiladigan xususiyat
Buyurtma da jami uchun setter yo'q. Klass ichidagi biror metod unga yozib ko'rsa nima bo'ladi?
class Buyurtma {
get jami() {
return 40000;
}
tozala() {
this.jami = 0;
}
}
const stol4 = new Buyurtma();
stol4.tozala();TypeError: Cannot set property jami of #<Buyurtma> which has only a getterTarjimasi: "Buyurtma nusxasining jami xususiyatiga yozib bo'lmaydi — unda faqat getter bor". #<Buyurtma> — Node nusxani shunday belgilaydi: "Buyurtma klassining biror nusxasi".
Klass tashqarisida esa bu xatoni hamma joyda ham ko'rmaysiz. Strict mode darsini eslang: klass ichidagi kod va modul fayllari (.mjs, type="module") doim strict. U yerda jim xatolar haqiqiy xatoga aylanadi. Saytdagi «Ishga tushir» tugmasi ham strict — u yerda ham TypeError ko'rasiz.
Oddiy, strict bo'lmagan <script> da esa stol4.jami = 0 hech narsa demaydi. Tayinlash shunchaki yo'qoladi va jami avvalgidek 40000 qoladi. Ikkala holatda ham qiymat o'zgarmaydi, farq faqat xato ko'rinishida.
Demak getter + setter yo'qligi = faqat o'qiladigan xususiyat. Tashqi kod buyurtma summasini "qo'lda" o'zgartira olmaydi — faqat taom qo'shib.
Tekshirib ko'ring:
Taomdagiset narxni o'chirib, faqatget narxqoldirsak,new Taom("Osh", 35000)nima bo'ladi?
Javob
Konstruktordagi this.narx = narx ham getter-only xususiyatga yozish bo'lib qoladi. Klass ichidagi kod doim strict, shuning uchun TypeError: Cannot set property narx of #<Taom> which has only a getter — nusxa umuman yaratilmaydi. Konstruktor setter'ga tayansa, setter albatta kerak. Yoki konstruktorda to'g'ridan-to'g'ri this.#narx = narx yozing (lekin unda tekshiruv o'tkazib yuboriladi).
2.5 Getter va setter qayerda yashaydi?
osh ning o'z xususiyatlariga qarang:
class Taom {
#narx = 0;
constructor(nom) {
this.nom = nom;
}
get narx() {
return this.#narx;
}
set narx(yangi) {
this.#narx = yangi;
}
}
const osh = new Taom("Osh");
console.log(Object.keys(osh)); // [ 'nom' ]
console.log(Object.getOwnPropertyNames(Taom.prototype));
// [ 'constructor', 'narx' ]narx nusxada yo'q — u Taom.prototype da. Getter va setter metodlar kabi prototipga yoziladi, hamma nusxa ularni bitta juftlikdan oladi (Prototip zanjiri). #narx qiymati esa har nusxada alohida, lekin Object.keys uni ko'rmaydi — private maydon oddiy xususiyat emas.
Xususiyat deskriptorlari darsidagi "accessor" deskriptorni eslang. Klassdagi get/set aynan shuni yaratadi:
class Taom {
get narx() {
return 1;
}
set narx(q) {}
}
const d = Object.getOwnPropertyDescriptor(Taom.prototype, "narx");
console.log(typeof d.get, typeof d.set, d.enumerable);
// function function falseenumerable: false — klass a'zolari sanalmaydi. Shuning uchun Object.keys va for...in ularni ko'rsatmaydi. Bu farqqa class ichidan darsida qaytamiz.
2.6 Getter qachon kerak, qachon metod?
Getter tashqaridan xususiyatdek ko'rinadi. Demak o'quvchi undan xususiyatdek xulq kutadi. Uch qoida:
- Tez bo'lsin.
stol4.jamini o'qigan odam u bir zumda qaytadi deb o'ylaydi. Serverdan ma'lumot olish yoki minglab elementni saralash — metod ishi:hisobotniTuz(). - Yon ta'sirsiz bo'lsin. Getter hech narsani o'zgartirmasin, ekranga chiqarmasin.
osh.narxni ikki marta o'qish ikki marta bir xil natija bersin. - Nomi — ot. Getter qiymat, shuning uchun
jami,soni,narx. Metod — ish, nomi fe'l:qosh,hisobla.
Tekshirib ko'ring:
get chekniChopEt()— printerga chek yuboradigan getter. Bu yaxshi fikrmi?
Javob
Yo'q. Bu yon ta'sir — printer ishlaydi. buyurtma.chekniChopEt ni DevTools'da shunchaki ko'rish uchun ochsangiz ham chek chiqib ketadi. Nomi ham fe'l — o'zi "men metodman" deyapti. To'g'risi: oddiy metod chekniChopEt(), qavs bilan chaqiriladi.
3. static: klassning o'z a'zolari
3.1 static maydon
Narx qaysi valyutada? Bu savol har taom uchun bir xil javob beradi. Uni klassga yozamiz:
class Taom {
static VALYUTA = "so'm";
constructor(nom, narx) {
this.nom = nom;
this.narx = narx;
}
}
const osh = new Taom("Osh", 35000);
console.log(Taom.VALYUTA); // so'm
console.log(osh.VALYUTA); // undefined
console.log(`${osh.narx} ${Taom.VALYUTA}`); // 35000 so'mstatic a'zo (static member) — nusxaga emas, klassning o'ziga tegishli maydon yoki metod. Unga klass nomi orqali murojaat qilinadi: Taom.VALYUTA. Nusxa orqali — osh.VALYUTA — topilmaydi.
Nega? Funksiya obyekt sifatida darsini eslang: funksiya ham obyekt, unga xususiyat qo'shsa bo'ladi. Klass ham funksiya (typeof Taom — "function"). static VALYUTA — shu funksiya-obyektning xususiyati, xolos. osh esa Taom.prototype dan meros oladi, Taom ning o'zidan emas. Ikki xil zanjir:
flowchart TB
K["Taom — klass (funksiya)<br/>static: VALYUTA, dan()"]
P["Taom.prototype<br/>get/set narx, metodlar"]
O["osh — nusxa<br/>nom, #narx"]
M["manti — nusxa<br/>nom, #narx"]
K -- ".prototype" --> P
O -- "[[Prototype]]" --> P
M -- "[[Prototype]]" --> PDiagrammada osh va manti dan chiquvchi strelkalar faqat Taom.prototype ga boradi. Taom ning o'ziga hech qaysi nusxadan yo'l yo'q — shuning uchun osh.VALYUTA topilmadi. static a'zo nusxalarning qidiruv zanjirida yo'q.
Bunday o'zgarmaslar odatda KATTA_HARF bilan yoziladi: static VALYUTA, static MAKS_NARX. Bu "o'zgartirilmaydi" degan kelishuv (let va const darsidagi nomlash uslublari).
3.2 static metod
Ikki taomni narx bo'yicha solishtirish — bu bitta taomning ishi emas. Ikkalasi teng huquqli. Bunday funksiya static metod bo'ladi:
class Taom {
constructor(nom, narx) {
this.nom = nom;
this.narx = narx;
}
static solishtir(a, b) {
return a.narx - b.narx;
}
}
const menyu = [
new Taom("Osh", 35000),
new Taom("Lag'mon", 28000),
new Taom("Manti", 30000),
];
const arzondan = menyu.toSorted(Taom.solishtir);
console.log(arzondan.map((t) => t.nom).join(", "));
// Lag'mon, Manti, OshTaom.solishtir — sort va taqqoslash funksiyasi darsidagi (a, b) imzosi. Uni qavssiz, to'g'ridan-to'g'ri toSorted ga berdik (Nusxa bilan o'zgartirish). Bu xavfsiz, chunki ichida this yo'q — faqat ikki parametr.
Qachon metod static bo'ladi? Oddiy savol bilan tekshiring: "Bu ishga bitta aniq nusxa kerakmi?" osh.narxniOshir(10) — ha, aynan osh. Taom.solishtir(a, b) — yo'q, ikki teng nusxa. Taom.dan(malumot) — yo'q, nusxa hali yo'q, uni endi yaratamiz.
3.3 Tanish static metodlar
Siz static metodlarni allaqachon o'nlab marta ishlatgansiz — faqat nomini bilmagansiz:
| Chaqiruv | Klass | Nega static |
|---|---|---|
Array.isArray(x) |
Array |
Hali massiv ekani noma'lum — x.isArray() deb bo'lmaydi |
Array.from("osh") |
Array |
Yangi massiv yaratadi (Array.from) |
Object.keys(obj) |
Object |
Har qanday obyekt uchun |
Number.isInteger(n) |
Number |
Har qanday qiymat uchun |
Endi Object.keys(osh) nega osh.keys() emasligi tushunarli: keys — Object klassining static metodi. osh da bunday metod yo'q va bo'lishi ham kerak emas — aks holda keys nomli maydoni bor obyekt metodni yashirib qo'yardi.
Tekshirib ko'ring:
[1, 2].isArray()nima beradi?
Javob
TypeError: [1,2].isArray is not a function. isArray — Array ning static metodi, u Array.prototype da yo'q. Massiv nusxasining zanjirida esa faqat Array.prototype bor. To'g'risi: Array.isArray([1, 2]) — true.
3.4 static ichida this va private static
Nechta taom yaratilganini sanaymiz. Hisoblagich bitta — klassda:
class Taom {
static #soni = 0;
constructor(nom) {
this.nom = nom;
Taom.#soni++;
}
static get soni() {
return this.#soni;
}
}
new Taom("Osh");
new Taom("Manti");
console.log(Taom.soni); // 2Uch yangi narsa:
static #soni— private static maydon. Klass tashqarisidanTaom.#soniga ham kirib bo'lmaydi; uni faqatTaom.sonigetteri orqali o'qish mumkin. Yozish esa — faqat konstruktorda. Hisoblagichni tashqaridan "aldab" bo'lmaydi.static get soni()— getter hamstaticbo'la oladi.Taom.soniqavssiz o'qiladi.staticmetod ichidathis— klassning o'zi.this: to'rt qoida darsidagi "nuqtadan oldingi obyekt" qoidasi:Taom.sonida nuqtadan oldinTaomturibdi. Shuning uchunthis.#soni—Taom.#sonibilan bir xil.
Qadamma-qadam ko'ring — Keyingi tugmasini bosib, Taom.#soni qayerda o'sishiga qarang:
3.5 Tuzoq: static metodni callback qilib berish
this "nuqtadan oldingi obyekt" bo'lsa, nuqta yo'qolganda nima bo'ladi? this yo'qolishi darsidagi muammo static metodlarda ham bor:
class Taom {
constructor(nom, narx) {
this.nom = nom;
this.narx = narx;
}
static dan(malumot) {
return new this(malumot.nom, malumot.narx);
}
}
const malumotlar = [{ nom: "Osh", narx: 35000 }];
const menyu = malumotlar.map(Taom.dan);TypeError: this is not a constructorTarjimasi: "this — konstruktor emas". map Taom.dan ni nuqtasiz, oddiy funksiya sifatida chaqirdi. Klass kodi doim strict — this undefined bo'ldi. new undefined(...) esa mumkin emas.
Ikki tuzatish:
- Chaqiruvni arrow funksiyaga o'rang:
malumotlar.map((m) => Taom.dan(m)). Nuqta saqlanadi. Bu Callback imzosi darsidagi tuzoqdan ham himoya qiladi:mapikkinchi argument sifatida indeksni ham beradi. - Yoki
staticmetod ichidathiso'rniga klass nomini yozing:new Taom(...).
Ikkinchi yo'l oddiyroq ko'rinadi, lekin this ning foydasi bor — uni Meros darsida ko'ramiz. Shuning uchun birinchi odat yaxshiroq: static metodni callback qilib berishda arrow bilan o'rang.
3.6 static {} bloki
Ba'zan klass e'lon qilinayotganda bir martalik hisob kerak bo'ladi. Masalan, menyudan eng arzon taomni topib, static maydonga yozib qo'yish. Buning uchun static {} bloki bor:
class Menyu {
static taomlar = [
{ nom: "Osh", narx: 35000 },
{ nom: "Lag'mon", narx: 28000 },
{ nom: "Manti", narx: 30000 },
];
static engArzon;
static {
const tartib = Menyu.taomlar.toSorted((a, b) => a.narx - b.narx);
Menyu.engArzon = tartib[0].nom;
console.log("static blok ishladi");
}
}
console.log(Menyu.engArzon);Konsolda:
static blok ishladi
Lag'monBlok klass e'lonining o'zida, bir marta bajariladi — bitta ham nusxa yaratilmagan bo'lsa ham. U yuqoridan pastga, static maydonlar bilan aralash tartibda ishlaydi: taomlar tayyor, keyin blok. Blok ichida klassning private a'zolariga ham kirish mumkin.
Amalda static {} kam uchraydi — ko'pincha oddiy static maydon yetarli. Lekin kutubxona kodida uchratasiz, shuning uchun tanib qo'ying.
4. Factory metod
4.1 Konstruktorning cheklovi
Konstruktor bitta va uning imzosi bitta: new Taom(nom, narx). Ma'lumot esa har xil shaklda keladi:
- Obyekt bo'lib —
{ nom: "Osh", narx: 35000 }(JSON asoslari darsidaJSON.parseaynan shunday obyekt qaytaradi). - Satr bo'lib — Otabek daftarga yozgan
"Osh:35000".
Har safar new Taom(m.nom, m.narx) yoki satrni bo'lib yozish — takrorlanadigan kod. Yechim — factory metod (factory method): yangi nusxani yasab qaytaradigan static metod. "Factory" — "zavod": xom ashyo kiradi, tayyor mahsulot chiqadi.
class Taom {
constructor(nom, narx) {
this.nom = nom;
this.narx = narx;
}
static dan(malumot) {
return new Taom(malumot.nom, malumot.narx);
}
static satrdan(satr) {
const [nom, narx] = satr.split(":");
return new Taom(nom, Number(narx));
}
}
const osh = Taom.dan({ nom: "Osh", narx: 35000 });
const manti = Taom.satrdan("Manti:30000");
console.log(osh, manti);Konsolda:
Taom { nom: 'Osh', narx: 35000 } Taom { nom: 'Manti', narx: 30000 }Har factory metodning nomi qaysi manbadan yaratilishini aytadi: dan — obyektdan, satrdan — satrdan. Ichida esa yagona yo'l — new Taom(...). Konstruktor o'zgarsa, faqat shu metodlar moslanadi; ularni chaqirgan yuzlab joy esa o'zgarmaydi.
Array.from(...), Object.fromEntries(...) — xuddi shu naqsh: "from" — "-dan". Biz o'zbekcha nom bilan yozdik: Taom.dan(...).
4.2 Qaysi biri qachon?
| Holat | Tanlov |
|---|---|
| Hamma ma'lumot qo'lda, aniq | new Taom("Osh", 35000) |
| Ma'lumot obyekt yoki satr bo'lib keladi | Taom.dan(...), Taom.satrdan(...) |
| Yaratishdan oldin tayyorlash kerak | factory metod (ichida tekshirish yoki tozalash) |
Factory metodni Closure amaliyotda darsidagi "fabrika funksiya" bilan adashtirmang. U yerda oddiy funksiya obyekt qaytarardi. Bu yerda esa — klassning static metodi, u klass nusxasini qaytaradi. G'oya bir xil: "yaratish ishini bitta joyga yig'ish". Bu g'oya JS'da dizayn naqshlari darsida alohida naqsh sifatida qaytadi.
Tekshirib ko'ring:
Taom.satrdan("Osh:35000").narxqanday turda bo'ladi?Number(...)ni unutsak-chi?
Javob
Number bilan — son, 35000. Usiz — satr, "35000": split doim satrlar qaytaradi. Keyin osh.narx + 5000 qo'shish o'rniga yopishtiradi — "350005000". Factory metodning foydasi shu: tur o'zgartirishni bir joyda qilib, hamma chaqiruvchini bu tuzoqdan qutqaradi.
5. Ko'p uchraydigan xatolar
5.1 Setter ichida o'ziga yozish
class Taom {
set narx(yangi) {
this.narx = yangi;
}
}
new Taom().narx = 35000;RangeError: Maximum call stack size exceededTarjimasi: "chaqiruvlar stekining eng katta o'lchamidan oshib ketildi" (Rekursiya asoslari). this.narx = yangi — yana narx ga yozish, ya'ni yana shu setter. U yana o'zini chaqiradi — cheksiz. Tuzatish: qiymatni boshqa joyda saqlang — this.#narx = yangi.
5.2 Maydon getterni yopib qo'yadi
class Taom {
narx = 0;
get narx() {
return 35000;
}
}
console.log(new Taom().narx); // 0Xato xabari yo'q, getter esa umuman ishlamadi. narx = 0 — maydon, u har nusxaning o'ziga yoziladi. Getter esa prototipda. Qidiruv nusxadan boshlanadi va 0 ni darhol topadi — prototipgacha yetmaydi (Shadowing). Tuzatish: bitta nomni ikki marta ishlatmang; qiymat — #narx da, getter — narx.
5.3 static a'zoni nusxadan chaqirish
class Taom {
static dan(m) {
return new Taom(m.nom, m.narx);
}
}
const osh = new Taom();
osh.dan({ nom: "Manti", narx: 30000 });TypeError: osh.dan is not a functiondan — klassda, nusxada yo'q. Tuzatish: Taom.dan(...). Teskari xato ham bor: oddiy metodni klassdan chaqirish — Taom.qosh() — Taom.qosh is not a function. Xabardagi nuqtadan oldingi so'zga qarang: nusxami yoki klassmi?
5.4 static metodni callback qilib berish
«static metodni callback qilib berish» bo'limidagi TypeError: this is not a constructor. Tuzatish: (m) => Taom.dan(m).
6. Mashqlar
1-mashq (oson): Bron va odam soni
«Bahor» bron formasida odam soni 1 dan 20 gacha. Bron klassini yozing: ism va odam maydoni, odam — #odam da, getter va setter bilan. Setter faqat 1–20 oralig'idagi butun sonni qabul qilsin, aks holda console.warn bilan ogohlantirsin. Ishora: butun sonni Number.isInteger tekshiradi.
Yechim
class Bron {
#odam = 1;
constructor(ism, odam) {
this.ism = ism;
this.odam = odam;
}
get odam() {
return this.#odam;
}
set odam(soni) {
if (!Number.isInteger(soni) || soni < 1 || soni > 20) {
console.warn(`Odam soni 1–20 bo'lsin: ${soni}`);
return;
}
this.#odam = soni;
}
}
const bron = new Bron("Malika", 4);
bron.odam = 25;
bron.odam = 6;
console.log(bron.odam);Konsolda:
Odam soni 1–20 bo'lsin: 25
6#odam = 1 — boshlang'ich qiymat. Konstruktorga noto'g'ri son berilsa (new Bron("Ali", 0)), setter uni rad etadi va nusxada 1 qoladi.
2-mashq (o'rta): Bronlar hisoblagichi va factory
Bron ga qo'shing:
static #sonivastatic get soni()— nechta bron yaratilgani.static satrdan(satr)—"Ali;4"kabi satrdan bron yasasin. Ishora:split(";")vaNumber(...).
Yechim
class Bron {
static #soni = 0;
constructor(ism, odam) {
this.ism = ism;
this.odam = odam;
Bron.#soni++;
}
static get soni() {
return Bron.#soni;
}
static satrdan(satr) {
const [ism, odam] = satr.split(";");
return new Bron(ism, Number(odam));
}
}
const bronlar = ["Ali;4", "Malika;2"].map((s) => Bron.satrdan(s));
console.log(bronlar[1]); // Bron { ism: 'Malika', odam: 2 }
console.log(Bron.soni); // 2Hisoblagich konstruktorda oshadi, shuning uchun satrdan orqali yaratilganlar ham sanaladi — factory ichida ham new Bron bor. map ga Bron.satrdan ni arrow bilan o'rab berdik — ichida this yo'q bo'lsa ham bu yaxshi odat.
3-mashq (qiyin): Savat
Savat klassini yozing:
#taomlar—{ nom, narx, soni }obyektlari massivi;qosh(nom, narx)— taom bor bo'lsa sonini oshirsin, yo'q bo'lsa yangisini qo'shsin.get jami— summa,get bosh— savat bo'shmi (true/false).static CHEGIRMA_CHEGARASI = 100000vaget chegirma— jami shu chegaradan oshsa, 10%, aks holda0.
Ishora: taomni find bilan qidiring, summani reduce bilan yig'ing.
Yechim
class Savat {
static CHEGIRMA_CHEGARASI = 100000;
#taomlar = [];
qosh(nom, narx) {
const bor = this.#taomlar.find((t) => t.nom === nom);
if (bor) {
bor.soni++;
} else {
this.#taomlar.push({ nom, narx, soni: 1 });
}
}
get jami() {
return this.#taomlar.reduce((s, t) => s + t.narx * t.soni, 0);
}
get bosh() {
return this.#taomlar.length === 0;
}
get chegirma() {
if (this.jami <= Savat.CHEGIRMA_CHEGARASI) {
return 0;
}
return this.jami / 10;
}
}
const savat = new Savat();
console.log(savat.bosh); // true
savat.qosh("Osh", 35000);
savat.qosh("Osh", 35000);
savat.qosh("Manti", 30000);
savat.qosh("Ko'k choy", 5000);
console.log(savat.jami, savat.chegirma); // 105000 10500chegirma getteri boshqa getterni — this.jami ni — o'qiydi. Getterlar bir-biriga tayanishi normal. #taomlar dagi obyektlarni bor.soni++ bilan o'zgartirish xavfsiz: ular tashqaridan ko'rinmaydi, faqat Savat ga tegishli. Savat.CHEGIRMA_CHEGARASI — klass nomi orqali, chunki u static.
4-mashq: Vazifalar qadami — Vazifa ga o'zgarmas va factory
Private # maydon darsida refactor/vazifa-klassi branch'i main ga qo'shildi. Bu va keyingi to'rt dars uchun yangi branch oching: git switch -c refactor/vazifalar-royxati. Oxirida vazifalar da VazifalarRoyxati klassi paydo bo'ladi.
Hozir Vazifa shunday (metod tanalari qisqartirilgan):
class Vazifa {
id;
bajarildi;
#matn;
constructor(id, matn, bajarildi = false) { ... }
get matn() { ... }
matnniOzgartir(yangi) { ... } // bo'sh yoki 100 dan uzun — false
toJSON() { ... }
almashtir() { ... }
}Ikki kichik muammo bor:
100soni ikki joyda yozilgan:matnniOzgartirichida (toza.length > 100) vatahrirQatorida (kiritma.maxLength = 100). Bu — "sehrli son". Biri o'zgarib, ikkinchisi unutilsa, maydon 150 belgini qabul qiladi,Vazifaesa rad etadi.holatoddiy obyektdan nusxa yasashni o'zi biladi:new Vazifa(v.id, v.matn, v.bajarildi)— uch maydon qo'lda sanab yozilgan. 11-qismda vazifalar saqlangan joydan ham oddiy obyekt bo'lib keladi — aynantoJSONqaytaradigan{ id, matn, bajarildi }shaklida. "Oddiy obyektdan nusxa" yo'li bitta bo'lsin vaVazifaning o'zida tursin.
Vazifa: static MAKS_UZUNLIK = 100 va static dan(malumot) factory metodini qo'shing, ikkala 100 ni va holat dagi new Vazifa(...) ni ularga almashtiring. Xulq o'zgarmasin.
Qo'shimcha savol: matnniOzgartir ni set matn(yangi) setter'iga aylantirish kerakmi?
Yechim
Vazifa ning boshi:
class Vazifa {
static MAKS_UZUNLIK = 100;
id;
bajarildi;
#matn;
constructor(id, matn, bajarildi = false) {
this.id = id;
this.#matn = matn;
this.bajarildi = bajarildi;
}
static dan(malumot) {
return new Vazifa(malumot.id, malumot.matn, malumot.bajarildi);
}matnniOzgartir ichida bitta o'zgarish:
if (toza === "" || toza.length > Vazifa.MAKS_UZUNLIK) {Holatning boshi — muzlatilgan oddiy ma'lumot, factory orqali:
const holat = {
vazifalar: boshlangichVazifalar.map(
(malumot) => Vazifa.dan(malumot),
),
filtr: "hammasi",
tahrirId: null,
// qoldi getter'i — avvalgidek
};Va tahrirQatori ichida:
kiritma.maxLength = Vazifa.MAKS_UZUNLIK;Nimaga e'tibor bering:
Vazifa.MAKS_UZUNLIK— klass nomi orqali, metod ichida ham. Qoida endi bitta joyda..map((malumot) => Vazifa.dan(malumot))— arrow bilan, «staticmetodni callback qilib berish» bo'limidagi odat.toJSONvadan— juftlik: biri nusxani oddiy obyektga aylantiradi, ikkinchisi oddiy obyektdan nusxa yasaydi. 11-qismda saqlash shu ikkisiga tayanadi.index.htmldagimaxlength="100"qoladi: HTML klassni o'qiy olmaydi. Brauzer foydalanuvchini kiritish paytida to'xtatadi,matnniOzgartiresa boshqa yo'l bilan kelgan matndan himoya qiladi. Ikkalasi bir xil bo'lishi kerakliginiVazifaga izoh qilib yozib qo'ying.
Setter kerakmi? Yo'q. matnniOzgartir true/false qaytaradi — chaqiruvchi o'zgarish qabul qilinganini biladi. Setter esa natija qaytara olmaydi: vazifa.matn = "" ifodasining qiymati doim o'ng tomondagi qiymat, setter nima qaytarishidan qat'i nazar. Rad etilgan matn haqida setter xabar berishining yagona yo'li — xato tashlash (throw). Shuning uchun natija kerak bo'lgan o'zgartirish — metod. Bu «Getter qachon kerak, qachon metod?» bo'limidagi tanlovning setter'dagi juftligi.
Xulq o'zgarmaganini tekshiring:
- Ochilganda — uch vazifa, "2 ta vazifa qoldi, 1 ta bajarildi".
- "DOM darsini takrorlash" ni tahrirlang:
DOM takrori(ikki chetida bo'sh joy) yozibEnter— ro'yxatda "DOM takrori", "O'zgarish saqlandi.", fokus «Tahrirlash» da. - Tahrir maydonida 100 tadan ortiq belgi yozib bo'lmaydi.
- Yangi vazifa, belgilash, o'chirish, filtrlar — hammasi avvalgidek.
Commit: Vazifalar: MAKS_UZUNLIK va Vazifa.dan qo'sh.
7. Real ishda
- Validatsiya qatlami. Domen klasslarida (
Foydalanuvchi,Buyurtma) setter qiymatni tekshiradi, getter esa hisoblanadigan maydonlarni beradi:buyurtma.jami,foydalanuvchi.toliqIsm. - Factory metodlar — deyarli har kutubxonada:
Array.from,Object.fromEntries,Date.now(),Promise.resolve(11-qismda). Backend'da serverdan kelgan obyektni klass nusxasiga aylantirish —Foydalanuvchi.dan(json)— har kungi ish. - O'zgarmaslar.
static MAKS_HAJM,static VERSIYA— klass bilan bog'liq qoidalar bir joyda turadi, kod bo'ylab sochilmaydi. - TypeScript va freymvorklar. TypeScript'da (15-qism)
staticva getter/setter aynan shunday yoziladi. NestJS (30-qism) va boshqa backend freymvorklaridastaticfactory metodlar ko'p uchraydi. - Intervyu. "
staticmetod nima va qachon ishlatiladi?", "getter va oddiy metodning farqi?" — junior va o'rta darajadagi klassik savollar. Javob:static— nusxa kerak bo'lmagan ish; getter — qiymat, xususiyatdek o'qiladi.
Xulosa
get/setklassda — xususiyat o'qilganda va yozilganda ishlaydigan funksiyalar; ularprototypeda,enumerable: false.#maydon+ getter + setter — qo'riqlangan xususiyat; setter yo'q bo'lsa — faqat o'qiladigan.- Getter tez, yon ta'sirsiz va ot bilan atalgan bo'lsin. Setter ichida o'ziga yozmang — cheksiz rekursiya. Natija qaytarishi kerak bo'lgan o'zgartirish — metod.
statica'zo klassning o'zida:Taom.VALYUTA,Taom.dan(). Nusxadan topilmaydi.staticmetod ichidathis— klass; callback qilib berishda arrow bilan o'rang.- Factory metod (
Taom.dan,Array.from) — har xil shakldagi ma'lumotdan nusxa yasashning bitta joyi.
Keyingi dars: Meros: extends va super — bir klassni boshqasi ustiga quramiz: ota klass xulqini olib, kerak joyini qayta yozamiz.
Manbalar
- MDN: "get", "set", "static", "Static initialization blocks" — developer.mozilla.org
- ECMAScript 2025 Language Specification: "ClassDefinitionEvaluation" — tc39.es/ecma262
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!