Mundarija (31)
- Bu darsda
- 1. Nega bu kerak?
- 2. extends: hamma narsa meros
- 2.1 Bo'sh bola klass
- 2.2 Bola klass konstruktori: super()
- 2.3 Qoida: this dan oldin super
- 2.4 Maydonlar qachon paydo bo'ladi?
- 3. Metodni qayta yozish va super.metod()
- 3.1 Override
- 3.2 super.tavsif() — ota versiyasini chaqirish
- 3.3 Getter va static ham meros
- 4. Ichkarida: ikki zanjir
- 4.1 Zanjir uzaysa
- 5. O'rnatilgan klasslardan meros
- 5.1 Array dan meros
- 5.2 Error dan meros
- 5.3 EventTarget dan meros
- 6. Meros qachon to'g'ri?
- 7. Ko'p uchraydigan xatolar
- 7.1 super() siz yoki undan oldin this
- 7.2 Ota konstruktori qayta yozilgan metodni chaqiradi
- 7.3 Nom xatosi override o'rniga yangi metod yaratadi
- 7.4 super.metod() ni unutish
- 8. Mashqlar
- 1-mashq (oson): Shirinlik
- 2-mashq (o'rta): VIP bron
- 3-mashq (qiyin): Hodisa yuboradigan bron daftari
- 4-mashq: Vazifalar qadami — tajriba: ro'yxat massivdan meros olsa-chi?
- 9. Real ishda
- Xulosa
- Manbalar
JavaScript klass merosi: extends va super bilan ota klass ustiga qurish
Qisqacha:
class Ichimlik extends Taom—IchimlikklassiTaomning hamma metodlarini meros oladi va o'zinikini qo'shadi. Bola klass konstruktoridathisdan oldinsuper(...)chaqirilishi shart: nusxani ota klass yaratadi. Metodni qayta yozsangiz (override), ota versiyasigasuper.metod()bilan murojaat qilasiz.
Bu darsda
extendsbilan bir klassni boshqasi ustiga qura olasiz.super(...)negathisdan oldin kelishi kerakligini tushuntira olasiz.- Metodni qayta yozib, ota versiyasini
super.metod()bilan chaqira olasiz. - Meros ikki zanjir — nusxalar va klasslar — bo'ylab qanday ishlashini chizib bera olasiz.
Array,ErrorvaEventTargetdan meros olishni va ularning o'ziga xos tomonlarini bilasiz.
Oldin bilishingiz kerak: Getter/setter va static a'zolar, Prototip zanjiri, Object.create va instanceof, Custom events va EventTarget.
1. Nega bu kerak?
«Bahor» menyusida Taom klassi bor: nomi, narxi va menyu qatorini yasaydigan tavsif() metodi. Endi Jasur aka ichimliklarni alohida ko'rsatmoqchi. Ichimlikda ham nom, narx va tavsif bor. Lekin ikkita qo'shimcha: hajmi (0.5 l) va issiq-sovuqligi.
Birinchi fikr — Taom ni nusxalab, Ichimlik deb nomlash va ikki maydon qo'shish. Ishlaydi. Lekin bir oydan keyin Jasur aka "narxga so'm qo'shib yozilsin" desa, ikki joyni tuzatish kerak bo'ladi. Uchinchi tur — Shirinlik — qo'shilsa, uch joyni. Bir joyini unutsangiz — menyuda ikki xil format chiqadi.
Hayotdan o'xshatish. Toshkent ko'chalaridagi oddiy Cobalt va Cobalt-taksi. Taksi — o'sha mashina: o'sha dvigatel, o'sha rul. Faqat ustida shashka, ichida hisoblagich. Zavod taksi uchun mashinani noldan loyihalamaydi — tayyor modelni olib, kerakli qismini qo'shadi. Dvigatel yaxshilansa, taksi ham avtomatik yaxshilanadi.
Klasslarda bu meros (inheritance) deyiladi: yangi klass mavjud klassning hamma xulqini oladi va faqat farq qiladigan joyini o'zi yozadi. Prototip zanjiri va Object.create darslarida merosning ichki mexanizmini ko'rgansiz. Bugun uning klassdagi qulay yozuvi — extends va super.
2. extends: hamma narsa meros
2.1 Bo'sh bola klass
Eng kichik meros — tanasi bo'sh klass:
class Taom {
constructor(nom, narx) {
this.nom = nom;
this.narx = narx;
}
tavsif() {
return `${this.nom} — ${this.narx} so'm`;
}
}
class Ichimlik extends Taom {}
const choy = new Ichimlik("Ko'k choy", 5000);
console.log(choy.tavsif());
console.log(choy instanceof Ichimlik, choy instanceof Taom);Konsolda:
Ko'k choy — 5000 so'm
true trueIchimlik da bitta ham qator yo'q, lekin uning nusxasi konstruktorni ham, tavsif() ni ham ishlatdi. extends Taom — "Ichimlik — Taom ning bir turi" degani.
Ikki atama: ota klass (parent class) — meros beradigan klass (Taom), bola klass (child class) — meros oladigan klass (Ichimlik). Kitoblarda "superclass" va "subclass" ham uchraydi — ma'nosi bir xil.
choy instanceof Taom — true. instanceof zanjir bo'ylab tekshiradi: choy — ichimlik, ichimlik esa — taom. Har ichimlik taom, lekin har taom ichimlik emas.
2.2 Bola klass konstruktori: super()
Endi Ichimlik ga hajm qo'shamiz. Buning uchun o'z konstruktori kerak:
class Taom {
constructor(nom, narx) {
this.nom = nom;
this.narx = narx;
}
}
class Ichimlik extends Taom {
constructor(nom, narx, hajm) {
super(nom, narx); // ota konstruktori ishlaydi
this.hajm = hajm; // keyin o'zimizniki
}
}
const choy = new Ichimlik("Ko'k choy", 5000, 0.5);
console.log(choy);
// Ichimlik { nom: "Ko'k choy", narx: 5000, hajm: 0.5 }super(nom, narx) — ota klass konstruktorini chaqirish. nom va narx ni qanday saqlashni Taom biladi, biz uni takrorlamaymiz. Ichimlik faqat o'z yangiligini — hajm ni — qo'shadi.
Node chiqishida nom: "Ko'k choy" qo'shtirnoqda — chunki satr ichida apostrof bor. Node satrni bitta tirnoqqa o'rasa, apostrof uni buzardi, shuning uchun qo'shtirnoqni tanladi. Qiymat o'sha.
2.3 Qoida: this dan oldin super
Tartibni almashtirib ko'ramiz:
class Taom {
constructor(nom, narx) {
this.nom = nom;
this.narx = narx;
}
}
class Ichimlik extends Taom {
constructor(nom, narx, hajm) {
this.hajm = hajm;
super(nom, narx);
}
}
new Ichimlik("Ko'k choy", 5000, 0.5);ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructorTarjimasi: "hosila (bola) klassda this ga murojaat qilishdan yoki konstruktordan qaytishdan oldin ota konstruktorini chaqirish shart". Xato turi — ReferenceError: this hali mavjud emas.
Nega? Konstruktor funksiya va new darsida new ning to'rt qadamini ko'rgan edik: birinchi qadam — bo'sh obyekt yaratish. Oddiy klassda bu obyektni new yaratadi. Bola klassda esa yaratmaydi — bu ishni ota klassga qoldiradi. Obyektni super() qaytaradi va shundagina u this ga aylanadi. super() gacha this — bo'sh joy.
Xabarning ikkinchi yarmi — "or returning" — super() ni umuman unutgan holat. Konstruktorda this ga tegmasangiz ham, super() siz tugatsangiz, xuddi shu xato chiqadi: qaytariladigan obyekt yo'q.
Bola klassda konstruktor yozmasangiz-chi? «Bo'sh bola klass» bo'limidagi Ichimlik ga o'xshab. Unda JavaScript yashirin konstruktor qo'shadi — barcha argumentlarni otaga uzatadigan:
constructor(...args) {
super(...args);
}Shuning uchun bo'sh Ichimlik ham ishladi. Konstruktor faqat qo'shimcha ish kerak bo'lganda yoziladi.
Tekshirib ko'ring: Quyidagi konstruktor ishlaydimi?
constructor(nom, narx) { const toliq = nom.trim(); super(toliq, narx); }
Javob
Ha. Qoida "konstruktorning birinchi qatori super bo'lsin" emas — "this dan oldin super bo'lsin". this ga tegmaydigan tayyorgarlik (argumentni tozalash, hisoblash) super dan oldin bo'lishi mumkin.
2.4 Maydonlar qachon paydo bo'ladi?
Class maydonlari darsida maydonlar konstruktordan oldin ishga tushishini ko'rgan edik. Bola klassda bitta aniqlik bor: bola maydonlari super() qaytgandan keyin yoziladi. this aynan shu paytda paydo bo'ladi. Qadamma-qadam qarang:
Tartib: ota maydonlari → ota konstruktori → bola maydonlari → bola konstruktorining qolgani. Konsoldagi xususiyatlar tartibi buni tasdiqlaydi: narx, nom, issiq, hajm.
3. Metodni qayta yozish va super.metod()
3.1 Override
choy.tavsif() hozir "Ko'k choy — 5000 so'm" qaytaradi. Ichimlik uchun hajm ham kerak: "Ko'k choy — 5000 so'm, 0.5 l". Bola klassda xuddi shu nomli metod yozamiz:
class Taom {
constructor(nom, narx) {
this.nom = nom;
this.narx = narx;
}
tavsif() {
return `${this.nom} — ${this.narx} so'm`;
}
}
class Ichimlik extends Taom {
constructor(nom, narx, hajm) {
super(nom, narx);
this.hajm = hajm;
}
tavsif() {
return `${super.tavsif()}, ${this.hajm} l`;
}
}
const menyu = [
new Taom("Osh", 35000),
new Ichimlik("Ko'k choy", 5000, 0.5),
];
menyu.forEach((t) => console.log(t.tavsif()));Konsolda:
Osh — 35000 so'm
Ko'k choy — 5000 so'm, 0.5 lQayta yozish (override) — bola klassda ota metodi bilan bir xil nomli metod yozish. Endi choy.tavsif() bola versiyasini chaqiradi. Nega? Qidiruv prototip zanjiri bo'ylab pastdan yuqoriga boradi: avval Ichimlik.prototype — u yerda tavsif bor, qidiruv to'xtaydi. Taom.prototype dagi versiyaga navbat kelmaydi. Bu — o'sha shadowing, faqat metodlar uchun.
3.2 super.tavsif() — ota versiyasini chaqirish
Bola tavsif ota formatini takrorlamadi. U super.tavsif() ni chaqirdi — "otamning tavsif i nima qaytarsa, o'shani ber" — va oxiriga hajm qo'shdi. Jasur aka narx formatini o'zgartirsa, faqat Taom.tavsif tuzatiladi — ichimliklar ham avtomatik yangilanadi.
super ikki xil ishlatiladi:
| Yozuv | Qayerda | Nima qiladi |
|---|---|---|
super(...) |
faqat bola konstruktorida | ota konstruktorini chaqiradi |
super.metod(...) |
har qanday metodda | ota prototipidagi metodni chaqiradi, this — o'sha nusxa |
Ikkinchisida this saqlanadi: super.tavsif() ichida this.nom — choyning nomi. Ota metodi "boshqa obyektda" emas, xuddi shu nusxada ishlaydi.
Bitta e'tibor: forEach callback'ida biz t ning qaysi klassdan ekanini so'ramadik. Har nusxa o'z tavsif ini o'zi bildi. Bir xil chaqiruv — har xil xulq. Bu polimorfizm deyiladi, uni OOP tamoyillari darsida batafsil ko'ramiz.
Tekshirib ko'ring:
Ichimlikdagitavsifichidasuper.tavsif()o'rnigathis.tavsif()yozilsa nima bo'ladi?
Javob
this.tavsif() — yana Ichimlik ning tavsif i, ya'ni o'zi. U yana o'zini chaqiradi — cheksiz rekursiya va RangeError: Maximum call stack size exceeded. super. aynan zanjirning bitta yuqorisidan qidirishni boshlaydi, shuning uchun o'ziga qaytib kelmaydi.
3.3 Getter va static ham meros
Meros faqat oddiy metodlar uchun emas. Oldingi darsdagi getter, setter va static a'zolar ham o'tadi:
class Taom {
static VALYUTA = "so'm";
constructor(nom, narx) {
this.nom = nom;
this.narx = narx;
}
static dan(malumot) {
return new this(malumot.nom, malumot.narx);
}
}
class Ichimlik extends Taom {}
const kompot = Ichimlik.dan({ nom: "Kompot", narx: 8000 });
console.log(kompot); // Ichimlik { nom: 'Kompot', narx: 8000 }
console.log(Ichimlik.VALYUTA); // so'mIchimlik.dan — Taom dan meros olingan static metod. Diqqat qiling: natija Ichimlik, Taom emas. Chunki dan ichida new this(...). Ichimlik.dan(...) da nuqtadan oldin Ichimlik turibdi, demak this — Ichimlik.
O'tgan darsda "static metodda this ning foydasi Meros darsida ko'rinadi" degan edik — mana u. new Taom(...) yozilganda bola klasslar ham Taom nusxasini olardi. new this(...) esa "kim chaqirgan bo'lsa, o'shaning nusxasi" degani.
4. Ichkarida: ikki zanjir
extends ikki havolani bog'laydi. Birinchisi nusxalar uchun, ikkinchisi — static a'zolar uchun:
class Taom {}
class Ichimlik extends Taom {}
const proto = Object.getPrototypeOf(Ichimlik.prototype);
console.log(proto === Taom.prototype); // true
console.log(Object.getPrototypeOf(Ichimlik) === Taom); // trueflowchart TB
T["Taom<br/>static: VALYUTA, dan()"]
I["Ichimlik"]
TP["Taom.prototype<br/>tavsif()"]
IP["Ichimlik.prototype<br/>tavsif() — qayta yozilgan"]
C["choy — nusxa<br/>nom, narx, hajm"]
I -- "[[Prototype]]" --> T
IP -- "[[Prototype]]" --> TP
C -- "[[Prototype]]" --> IP
I -. ".prototype" .-> IP
T -. ".prototype" .-> TPDiagrammada ikki zanjirni toping (uzluksiz [[Prototype]] o'qlari). Birinchisi — nusxalar zanjiri: choy → Ichimlik.prototype → Taom.prototype. choy.tavsif() shu yo'l bilan qidiriladi. Ikkinchisi — klasslar zanjiri: Ichimlik → Taom. Ichimlik.dan va Ichimlik.VALYUTA shu yo'l bilan topiladi. Uzuq chiziqlar — har klassning o'z prototype iga havolasi.
super.tavsif() ham shu diagramma bo'yicha ishlaydi: u Ichimlik.prototype ning bitta yuqorisidan — Taom.prototype dan — qidiradi. super bu "yuqori"ni metod qaysi klassda yozilganiga qarab topadi, chaqirilgan obyektga qarab emas. Bu nozik farq class ichidan darsida qaytadi.
Object.create darsida xuddi shunday zanjirni qo'lda qurgan edik. extends — o'sha mexanizmning qisqa yozuvi, yangi mexanizm emas.
4.1 Zanjir uzaysa
Bola klassdan ham meros olish mumkin. Ko'k choy — ichimlikning bir turi, ichimlik — taomning:
class Taom {
tavsif() {
return "taom";
}
}
class Ichimlik extends Taom {
tavsif() {
return `${super.tavsif()} → ichimlik`;
}
}
class IssiqIchimlik extends Ichimlik {
tavsif() {
return `${super.tavsif()} → issiq`;
}
}
const choy = new IssiqIchimlik();
console.log(choy.tavsif()); // taom → ichimlik → issiq
console.log(choy.constructor.name); // IssiqIchimlik
console.log(choy instanceof Taom); // trueHar super.tavsif() bitta qavat yuqoriga chiqdi va natija pastdan yuqoriga yig'ildi. choy.constructor.name — nusxa qaysi klassdan yaratilganini aytadi: constructor xususiyati prototipdan keladi (Konstruktor funksiya va new).
Texnik jihatdan zanjir istalgancha uzun bo'lishi mumkin. Amalda esa ikki-uch qavatdan oshsa, kodni o'qish qiyinlashadi. choy.tavsif() nima qaytarishini bilish uchun uchta klassni yuqoridan pastgacha o'qib chiqish kerak. Bitta qavatdagi o'zgarish pastdagi hamma klassga ta'sir qiladi — va siz ularning hammasini eslab yurolmaysiz.
Shuning uchun tajribali jamoalarda qoida bor: meros zanjiri sayoz bo'lsin. Chuqur ierarxiya kerak bo'lib qolsa — bu ko'pincha noto'g'ri tanlov belgisi. Muqobilini keyingi darsda ko'ramiz.
Tekshirib ko'ring:
IssiqIchimlikdagitavsifni o'chirsak,choy.tavsif()nima qaytaradi?
Javob
"taom → ichimlik". Qidiruv IssiqIchimlik.prototype da tavsif ni topmaydi va bir qavat yuqoriga — Ichimlik.prototype ga — chiqadi. U yerdagi versiya super.tavsif() orqali Taom nikini oladi va " → ichimlik" qo'shadi. "→ issiq" qismini yozadigan metod endi yo'q.
5. O'rnatilgan klasslardan meros
extends dan keyin faqat o'zingiz yozgan klass emas, JavaScript'ning o'z klasslari ham kelishi mumkin. Uchta muhimini ko'ramiz.
5.1 Array dan meros
class Buyurtmalar extends Array {
get jami() {
return this.reduce((s, b) => s + b.narx, 0);
}
}
const bugun = new Buyurtmalar();
bugun.push(
{ taom: "Osh", narx: 35000 },
{ taom: "Manti", narx: 30000 },
);
console.log(bugun.jami); // 65000
const qimmat = bugun.filter((b) => b.narx > 32000);
console.log(qimmat instanceof Buyurtmalar); // true
console.log(qimmat.jami); // 35000Massivning hamma metodi ishlaydi, ustiga jami getteri qo'shildi. Qiziq tomoni: filter oddiy massiv emas, Buyurtmalar qaytardi. JavaScript yangi massivni "kim chaqirgan bo'lsa, o'sha klassdan" yasaydi — static dan dagi new this(...) ga o'xshab. Shuning uchun qimmat.jami ham ishladi.
Lekin bitta g'alati joyi bor:
class Buyurtmalar extends Array {}
console.log(new Buyurtmalar(3)); // Buyurtmalar(3) [ <3 empty items> ]
console.log(new Buyurtmalar(3).length); // 3Array konstruktori bitta son olsa, uni uzunlik deb tushunadi va uch "teshikli" bo'sh joy yaratadi (Massivga o'xshash obyektlar va teshikli massivlar). Bola klass bu xulqni ham meros oldi. Massivdan meros olgan klassda konstruktorni o'zgartirish xavfli — filter va map ham uni ichkarida chaqiradi. Amalda massivdan meros kam olinadi; nega — keyingi darsda.
5.2 Error dan meros
Stack trace va xato turlari darsida TypeError, ReferenceError, RangeError ni ko'rdingiz. Ularning hammasi Error klassidan meros oladi. O'z xato turingizni ham shunday yasash mumkin:
class TaomTugadiXatosi extends Error {
constructor(taom) {
super(`${taom} tugadi`);
this.name = "TaomTugadiXatosi";
}
}
const xato = new TaomTugadiXatosi("Manti");
console.log(xato.message); // Manti tugadi
console.log(xato instanceof Error); // true
console.log(String(xato)); // TaomTugadiXatosi: Manti tugadisuper(...) ga xabar matni berildi — Error uni message ga yozadi. this.name — xato turining nomi; konsolda u xabar oldidan chiqadi, xuddi TypeError: kabi.
Bu yerda xatoni faqat yaratdik. Uni "tashlash" (throw) — dasturni to'xtatib, xatoni yuqoriga yuborish — va ushlash (try/catch) xatolar bilan ishlash darslarida. O'z xato klasslaringiz uchun alohida dars ham bor: O'z xato klasslaringiz. Hozir faqat shuni bilib qo'ying: xato turlari ham oddiy klass merosi.
5.3 EventTarget dan meros
Custom events va EventTarget darsining oxirida bitta kodni "hozir tushunish shart emas" deb ko'rsatgan edik. Endi uning har qatorini o'qiy olasiz:
class Savat extends EventTarget {
taomlar = [];
qosh(taom) {
this.taomlar.push(taom);
this.dispatchEvent(
new CustomEvent("ozgardi", { detail: this.taomlar.length }),
);
}
}
const savat = new Savat();
savat.addEventListener("ozgardi", (event) => {
console.log(`Savatda: ${event.detail} ta`);
});
savat.qosh("Osh");
savat.qosh("Ko'k choy");Konsolda:
Savatda: 1 ta
Savatda: 2 taextends EventTarget—SavatnusxasidaaddEventListenervadispatchEventbor. UlarEventTarget.prototypedan keladi.- Konstruktor yozilmagan — yashirin
super()ishladi,EventTargeto'z ichki ro'yxatini tayyorladi. O'z konstruktorini yozsangiz,super()ni unutmang. taomlar = []— bola maydoni,super()dan keyin paydo bo'ladi.this.dispatchEvent(...)—Savato'zi haqida e'lon qiladi. Kim tinglayotganini bilmaydi.
Bu naqsh — "obyekt o'zgarsa, tinglovchilarga xabar beradi" — JS'da dizayn naqshlari darsida "Kuzatuvchi" nomi bilan qaytadi. EventTarget va CustomEvent Node'da ham bor, shuning uchun kod "Ishga tushir" tugmasi bilan ishlaydi.
6. Meros qachon to'g'ri?
Oddiy tekshiruv bor — "...ning bir turi" savoli. Gapni ovoz chiqarib ayting:
- "Ichimlik — taomning bir turi". To'g'ri eshitiladi — meros mos.
- "Taksi — mashinaning bir turi". To'g'ri.
- "Savat — taomning bir turi". Yo'q! Savatda taomlar bor, lekin u o'zi taom emas.
Ikkinchi holatda meros noto'g'ri tanlov. "Bor" munosabati boshqacha quriladi — bir obyekt boshqasini ichida saqlaydi. Bu keyingi darsning mavzusi: kompozitsiya. U yerda merosning narxini ham ko'ramiz — nega tajribali dasturchilar uni ehtiyot bilan ishlatadi.
Tekshirib ko'ring:
class Stol extends Choyxona— «Bahor» stollari uchun yaxshi fikrmi?
Javob
Yo'q. "Stol — choyxonaning bir turi" — noto'g'ri gap. Choyxonada stollar bor. Meros bilan Stol choyxonaning ish vaqti, manzili va menyusini ham olib qo'yardi — ular stolga tegishli emas. To'g'risi: Choyxona ichida stollar ro'yxati.
7. Ko'p uchraydigan xatolar
7.1 super() siz yoki undan oldin this
«this dan oldin super» bo'limidagi ReferenceError: Must call super constructor in derived class.... Xabarda "derived class" (hosila klass) so'zi bo'lsa — darhol bola konstruktorining boshiga qarang. Tuzatish: super(...) ni this ga birinchi murojaatdan oldin chaqiring.
7.2 Ota konstruktori qayta yozilgan metodni chaqiradi
class Taom {
constructor(nom) {
this.nom = nom;
console.log(this.tavsif());
}
tavsif() {
return this.nom;
}
}
class Ichimlik extends Taom {
hajm = 0.5;
tavsif() {
return `${this.nom}, ${this.hajm} l`;
}
}
new Ichimlik("Ko'k choy"); // Ko'k choy, undefined lXato xabari yo'q, lekin hajm undefined. Ota konstruktori bola tavsif ini chaqirdi — u qayta yozilgan. Lekin bola maydonlari (hajm) super() qaytgandan keyin yoziladi — «Maydonlar qachon paydo bo'ladi?» bo'limidagi tartib. Tuzatish: konstruktorda qayta yoziladigan metodni chaqirmang; chiqarish kerak bo'lsa — nusxa tayyor bo'lgach, tashqarida.
7.3 Nom xatosi override o'rniga yangi metod yaratadi
Ichimlik da tavsif o'rniga tafsif yozsangiz, xato chiqmaydi. Bu shunchaki yangi metod bo'ladi, choy.tavsif() esa jimgina ota versiyasini chaqiraveradi. Natija "noto'g'ri formatda" chiqadi va sababini topish qiyin. TypeScript (15-qism) buni override kalit so'zi bilan ushlaydi. Hozircha — nomni ota klassdan nusxalab oling.
7.4 super.metod() ni unutish
Bola tavsif ni qayta yozib, ota formatini qo'lda takrorlasangiz — meros foydasi yo'qoladi. Ota formati o'zgarsa, bola eskisida qoladi. Tuzatish: otaning ishini qayta yozmang — super.tavsif() ni chaqirib, ustiga qo'shing.
8. Mashqlar
1-mashq (oson): Shirinlik
Taom dan meros oladigan Shirinlik klassini yozing: qo'shimcha shakarsiz maydoni (true/false), tavsif() — ota tavsifi va shakarsiz bo'lsa oxirida " (shakarsiz)".
class Taom {
constructor(nom, narx) {
this.nom = nom;
this.narx = narx;
}
tavsif() {
return `${this.nom} — ${this.narx} so'm`;
}
}Yechim
class Taom {
constructor(nom, narx) {
this.nom = nom;
this.narx = narx;
}
tavsif() {
return `${this.nom} — ${this.narx} so'm`;
}
}
class Shirinlik extends Taom {
constructor(nom, narx, shakarsiz) {
super(nom, narx);
this.shakarsiz = shakarsiz;
}
tavsif() {
const qoshimcha = this.shakarsiz ? " (shakarsiz)" : "";
return super.tavsif() + qoshimcha;
}
}
const halva = new Shirinlik("Halva", 12000, true);
const pishiriq = new Shirinlik("Pishiriq", 9000, false);
console.log(halva.tavsif());
console.log(pishiriq.tavsif());Konsolda:
Halva — 12000 so'm (shakarsiz)
Pishiriq — 9000 so'mShart bo'yicha qo'shimcha bo'sh satr bo'lishi mumkin — super.tavsif() + "" ota natijasini o'zgarishsiz qaytaradi. Halva va pishiriq narxlari — misol uchun, «Bahor» menyusida ular yo'q.
2-mashq (o'rta): VIP bron
Bron klassida ism, odam va narx() metodi bor: har odamga 10 000 so'm xizmat haqi. VipBron yozing: u alohida xona uchun qo'shimcha 50 000 so'm oladi. narx() ni qayta yozing va super.narx() dan foydalaning.
class Bron {
constructor(ism, odam) {
this.ism = ism;
this.odam = odam;
}
narx() {
return this.odam * 10000;
}
}Yechim
class Bron {
constructor(ism, odam) {
this.ism = ism;
this.odam = odam;
}
narx() {
return this.odam * 10000;
}
}
class VipBron extends Bron {
static XONA_NARXI = 50000;
narx() {
return super.narx() + VipBron.XONA_NARXI;
}
}
const bronlar = [new Bron("Ali", 4), new VipBron("Malika", 6)];
bronlar.forEach((b) => console.log(b.ism, b.narx()));Konsolda:
Ali 40000
Malika 110000VipBron da konstruktor yo'q — yashirin super(...args) ishladi. forEach ichida qaysi bron ekanini tekshirmadik: har biri o'z narx ini bildi.
3-mashq (qiyin): Hodisa yuboradigan bron daftari
BronDaftari extends EventTarget klassini yozing:
#bronlar = []vaqosh(ism, odam)— bronni qo'shib,"qoshildi"hodisasinidetail: { ism, odam }bilan yuborsin.get jamiOdam— barcha bronlardagi odamlar soni.
Ikki tinglovchi qo'ying: biri "Yangi bron: Ali, 4 kishi" deb yozsin, ikkinchisi — jami odamni. Ishora: hodisa obyekti va detail — Custom events darsida.
Yechim
class BronDaftari extends EventTarget {
#bronlar = [];
qosh(ism, odam) {
this.#bronlar.push({ ism, odam });
this.dispatchEvent(
new CustomEvent("qoshildi", { detail: { ism, odam } }),
);
}
get jamiOdam() {
return this.#bronlar.reduce((s, b) => s + b.odam, 0);
}
}
const daftar = new BronDaftari();
daftar.addEventListener("qoshildi", (event) => {
const { ism, odam } = event.detail;
console.log(`Yangi bron: ${ism}, ${odam} kishi`);
});
daftar.addEventListener("qoshildi", () => {
console.log(`Jami: ${daftar.jamiOdam} kishi`);
});
daftar.qosh("Ali", 4);
daftar.qosh("Malika", 2);Konsolda:
Yangi bron: Ali, 4 kishi
Jami: 4 kishi
Yangi bron: Malika, 2 kishi
Jami: 6 kishi#bronlar private — tashqi kod bronni faqat qosh orqali qo'sha oladi, demak har qo'shishda hodisa albatta yuboriladi. Ikkinchi tinglovchi daftar.jamiOdam ni o'qidi: hodisa sinxron, shuning uchun bron allaqachon ro'yxatda.
4-mashq: Vazifalar qadami — tajriba: ro'yxat massivdan meros olsa-chi?
Keyingi darsda vazifalar uchun VazifalarRoyxati klassini yasaymiz — vazifalar to'plamini boshqaradigan obyekt. Bugun birinchi xayolga keladigan yo'lni sinab ko'ring: massivdan meros. Bu tajriba vazifalar ga emas, mashqlar repo'siga tushadi.
mashqlar/10/40-meros/royxat-tajriba.mjs faylini yarating:
class Vazifa {
constructor(id, matn, bajarildi = false) {
this.id = id;
this.matn = matn;
this.bajarildi = bajarildi;
}
}
class VazifalarRoyxati extends Array {
get qoldi() {
return this.filter((v) => !v.bajarildi).length;
}
}
const royxat = new VazifalarRoyxati();
royxat.push(
new Vazifa(1, "Non olish"),
new Vazifa(2, "DOM darsini takrorlash", true),
);
console.log(royxat.qoldi); // 1Ishlaydi va qisqa. Endi faylning oxiriga uchta "begona" qator qo'shing va har biridan keyin royxat ni konsolga chiqaring:
royxat.push("salom")royxat[5] = nullroyxat.length = 0
Terminalda node royxat-tajriba.mjs bilan ishga tushiring. Har biri nima qildi? vazifalar ilovasi uchun bu xavflimi? Bitta gap bilan javob yozing: "VazifalarRoyxati — massivning bir turimi?"
Yechim
class Vazifa {
constructor(id, matn, bajarildi = false) {
this.id = id;
this.matn = matn;
this.bajarildi = bajarildi;
}
}
class VazifalarRoyxati extends Array {
get qoldi() {
return this.filter((v) => !v.bajarildi).length;
}
}
const royxat = new VazifalarRoyxati();
royxat.push(new Vazifa(1, "Non olish"));
royxat.push("salom");
console.log(royxat.length, royxat.qoldi);
royxat[5] = null;
console.log(royxat.length);
royxat.length = 0;
console.log(royxat.length, royxat.qoldi);Konsolda:
2 2
6
0 0Uchala qator ham xatosiz o'tdi:
"salom"vazifa emas, lekin ro'yxatga kirdi va hatto "faol" deb sanaldi: satrdabajarildiyo'q,!undefined—true.royxat[5] = null— uzunlik 6 ga sakradi, orada teshiklar paydo bo'ldi.royxat.length = 0— hamma vazifa bir zumda yo'qoldi.
Array dan meros bilan VazifalarRoyxati massivning hamma imkoniyatlarini oldi — 30 dan ortiq metod va to'g'ridan-to'g'ri indeks bilan yozish. Ularning har biri ilovaning qoidalarini (faqat Vazifa, id takrorlanmaydi) chetlab o'tadigan eshik. yangiId generatoriga esa massivda joy yo'q — u yana tashqarida qoladi.
Javob: yo'q, VazifalarRoyxati massivning bir turi emas. Unda vazifalar bor. «Meros qachon to'g'ri?» bo'limidagi tekshiruvdan o'tmadi. Keyingi darsda boshqa yo'lni tanlaymiz: massivni klass ichiga yashirib, tashqariga faqat kerakli amallarni chiqaramiz.
Commit (mashqlar repo): 10/40: VazifalarRoyxati extends Array tajribasi.
9. Real ishda
- Xato ierarxiyasi. Backend'da
class TopilmadiXatosi extends Error,class RuxsatYoqXatosi extends Error— server xato turiga qarab mijozga 404 yoki 403 javob qaytaradi (25-qism, Express). - Web Components. Brauzerda o'z HTML tegingizni yaratish
class TaomKarta extends HTMLElementbilan boshlanadi (Web Components). Bu yerdasuper()majburiy va konstruktor qoidalari aynan shu darsdagidek. - Node.js ichida. Node'dagi server, fayl oqimlari va boshqa ko'p obyektlar
EventEmitterdegan klassdan meros oladi —EventTargetning Node'dagi "qarindoshi". Shuning uchun ularning hammasida bir xilon(...)vaemit(...)metodlari bor. Node'ni 24-qismda chuqur o'rganamiz, hozir bilish shart emas — faqat meros u yerda ham asosiy g'oya ekanini eslab qoling. - Freymvorklar. Eski React kodida
class Tugma extends React.Component, NestJS'da xato va filtr klasslari — meros. Zamonaviy React funksiyalarga o'tgan, lekin eski loyihalarda klass komponentlarni o'qishingiz kerak bo'ladi (17-qism). - Intervyu. "
super()ni negathisdan oldin chaqirish kerak?", "extendsichkarida nima qiladi?", "super.method()vathis.method()farqi?" — o'rta darajadagi tez-tez beriladigan savollar. Bu darsdagi ikki zanjir diagrammasini chizib bersangiz — mavzuni ichidan bilishingiz ko'rinadi.
Xulosa
class B extends A—BnusxalariAning metodlarini,Bning o'zi esaAningstatica'zolarini meros oladi.- Bola konstruktorida
thisdan oldinsuper(...)— obyektni ota klass yaratadi. Konstruktor yozilmasa, yashirinsuper(...args)ishlaydi. - Tartib: ota maydonlari → ota konstruktori → bola maydonlari → bola konstruktorining qolgani.
- Override — bir xil nomli metod; ota versiyasi —
super.metod(),thissaqlanadi. Array,Error,EventTargetdan ham meros olish mumkin; har birining o'ziga xos tomoni bor.- Meros faqat "...ning bir turi" munosabatida. "Ichida bor" bo'lsa — boshqa yo'l kerak.
Keyingi dars: OOP tamoyillari va kompozitsiya — OOP'ning to'rt ustunini ko'ramiz va nega ko'pincha meros o'rniga kompozitsiya tanlanishini vazifalar da amalda ko'rsatamiz.
Manbalar
- MDN: "extends", "super", "Classes — Inheritance" — developer.mozilla.org
- MDN: "Error — Custom error types", "EventTarget() constructor" — developer.mozilla.org
- ECMAScript 2025 Language Specification: "ClassDefinitionEvaluation", "SuperCall" — tc39.es/ecma262
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!