Mundarija (38)
- Bu darsda
- 1. Nega bu kerak?
- 2. Birinchi konstruktor
- 2.1 Yozish va chaqirish
- 2.2 Nom qoidasi
- 3. new ning to'rt qadami
- 3.1 Qadamlar
- 3.2 new ichidan: o'zimizning yangi
- 3.3 4-qadamning nozik joyi
- 4. F.prototype — nusxalar uchun prototip
- 4.1 Har funksiyada bor
- 4.2 prototype va [[Prototype]] — eng ko'p chalkashtiriladigan juftlik
- 5. Metodlarni prototipga qo'yish
- 5.1 Bitta metod — hamma uchun
- 5.2 Ma'lumot — o'zida, metod — prototipda
- 5.3 Prototip jonli — keyin qo'shilgan metod ham ishlaydi
- 6. constructor xususiyati
- 6.1 Nusxa o'z konstruktorini "biladi"
- 6.2 Tuzoq: prototype ni butunlay almashtirish
- 7. new siz chaqirish
- 7.1 Xato yoki jim buzilish
- 7.2 new.target bilan himoya
- 7.3 O'rnatilgan konstruktorlar
- 8. Klassga ko'prik
- 9. Ko'p uchraydigan xatolar
- 9.1 new ni unutish
- 9.2 Arrow konstruktor yoki arrow metod
- 9.3 Massivni prototipga qo'yish
- 9.4 prototype ni almashtirib constructor ni yo'qotish
- 9.5 osh.prototype ga metod qo'shish
- 10. Mashqlar
- 1-mashq (oson): Stol
- 2-mashq (o'rta): Buyurtma va jami summa
- 3-mashq (qiyin): Nechta taom yasaldi?
- 4-mashq: Mashqlar papkasi — «Bahor» menyusi konstruktor bilan
- 11. Real ishda
- Xulosa
- Manbalar
JavaScript konstruktor funksiya va new: to'rt qadam va prototype
Qisqacha: Konstruktor funksiya —
newbilan chaqiriladigan oddiy funksiya, nomi katta harf bilan:new Taom("Osh", 35000). Bundanewto'rt qadam bajaradi: yangi bo'sh obyekt yaratadi, uning prototipiniTaom.prototypega ulaydi, funksiyani shu obyektnithisqilib chaqiradi va (funksiya boshqa obyekt qaytarmasa) yangi obyektni qaytaradi. Har obyektga xos ma'lumot konstruktordathisga yoziladi, umumiy metodlar esaTaom.prototypega — ular barcha nusxalar uchun bitta.
Bu darsda
- Konstruktor funksiya yozib,
newbilan bir xil tuzilishdagi ko'p obyekt yasay olasiz. newning to'rt qadamini aytib bera olasiz va uni o'zingiz qo'lda yozib ko'rsatasiz.F.prototypeva[[Prototype]]farqini,constructorxususiyatini tushuntira olasiz.- Metodlarni prototipga qo'yib, xotirani tejaysiz va har obyektning o'z holatini to'g'ri saqlaysiz.
newsiz chaqirish xatosini taniysiz va undan himoyalanasiz.
Oldin bilishingiz kerak: Prototip va prototip zanjiri, this: to'rt qoida, call, apply, bind, Shorthand va metodlar.
1. Nega bu kerak?
«Bahor» menyusida 40 ga yaqin taom bor. Har biri — obyekt: nomi, narxi va chekda qanday ko'rinishi. Literal bilan yozsak:
const osh = {
nom: "Osh",
narx: 35000,
chekQatori() {
return `${this.nom}: ${this.narx} so'm`;
},
};
const manti = {
nom: "Manti",
narx: 30000,
chekQatori() {
return `${this.nom}: ${this.narx} so'm`;
},
};
// ... yana 38 taUch muammo ko'rinib turibdi. Birinchisi — takror: bir xil chekQatori 40 marta yoziladi. Ikkinchisi — xato xavfi: bitta obyektda narx o'rniga narxi yozilsa, hech kim sezmaydi. Uchinchisi — xotira: har obyektda chekQatori ning alohida nusxasi turadi.
Takrorni oddiy funksiya bilan yo'qotish mumkin — obyekt qaytaradigan "fabrika":
function taomYarat(nom, narx) {
return {
nom,
narx,
chekQatori() {
return `${this.nom}: ${this.narx} so'm`;
},
};
}
const osh = taomYarat("Osh", 35000);
const manti = taomYarat("Manti", 30000);
console.log(osh.chekQatori === manti.chekQatori); // falseYozuv qisqardi, lekin uchinchi muammo qoldi: false — har chaqiruvda yangi chekQatori yaratildi. 40 taom — 40 ta bir xil funksiya.
O'tgan darsda yechimni ko'rgan edik: umumiy metod prototipda tursin, har obyekt uni zanjir orqali olsin. U yerdagi 2-mashqda esa har obyektga o'z massivini qo'lda berishga to'g'ri keldi. Ikkala ishni bitta qadamda bajaradigan vosita — konstruktor funksiya va new.
Hayotdan o'xshatish: g'isht qolipi. Qolip bitta. Har safar unga loy solinadi va yangi g'isht chiqadi — har biri alohida, o'z joyida turadi. Lekin hammasi bir xil shaklda, chunki qolip bitta. Konstruktor — qolip, new — qolipga loy solish, chiqqan obyekt — g'isht.
2. Birinchi konstruktor
2.1 Yozish va chaqirish
function Taom(nom, narx) {
this.nom = nom;
this.narx = narx;
}
const osh = new Taom("Osh", 35000);
const manti = new Taom("Manti", 30000);
console.log(osh); // Taom { nom: 'Osh', narx: 35000 }
console.log(manti.narx); // 30000Taom — oddiy funksiya. Uni maxsus qiladigan narsa — chaqiruvdagi new. this: to'rt qoida darsidagi 4-qoida ishladi: new bilan chaqirilganda this — yangi obyekt. Funksiya ichida return yo'q, lekin new yangi obyektni o'zi qaytardi.
Node obyekt oldiga Taom deb yozdi — "bu obyektni Taom yasagan". U buni qayerdan biladi — «constructor xususiyati» bo'limida ko'ramiz.
Konstruktor funksiya (constructor function) — new bilan chaqirib, obyekt yasash uchun yozilgan funksiya. Yasalgan obyekt — nusxa (instance): osh — Taom ning nusxasi.
2.2 Nom qoidasi
Konstruktor nomi katta harf bilan boshlanadi: Taom, Buyurtma, Stol. Bu JavaScript qoidasi emas, kelishuv — lekin juda muhim: kodni o'qigan odam "bu new bilan chaqiriladi" deb darhol tushunadi. O'rnatilgan konstruktorlar ham shunday: Date, Array, Map.
Nom — ot, fe'l emas. Kursdagi qoidaga ko'ra, qiymat qaytaradigan funksiya natija nomi bilan ataladi (Funksiya e'lon qilish va chaqirish darsidagi nomlash). Konstruktorning natijasi — taom, demak nomi Taom. taomYarat esa oddiy funksiya — u fe'l bilan.
Tekshirib ko'ring:
new Taom("Lag'mon", 28000)qanday obyekt qaytaradi?thisqayerga qaraydi?
Javob
Taom { nom: "Lag'mon", narx: 28000 }. new yangi bo'sh obyekt yaratdi va funksiyani shu obyektni this qilib chaqirdi. this.nom = nom — yangi obyektga yozdi. Funksiya tugagach, new o'sha obyektni qaytardi.
3. new ning to'rt qadami
3.1 Qadamlar
new Taom("Osh", 35000) yozilganda JavaScript aynan to'rt ish qiladi:
- Yangi bo'sh obyekt yaratadi:
{}. - Uning prototipini ulaydi: yangi obyektning
[[Prototype]]i —Taom.prototype. - Funksiyani chaqiradi:
this— shu yangi obyekt, argumentlar —"Osh",35000. - Natijani qaytaradi: funksiya o'zi boshqa obyekt qaytarmasa — yangi obyektni.
Ikkinchi qadamga e'tibor bering — u yangi. Taom.prototype nima ekanini «F.prototype — nusxalar uchun prototip» bo'limida ko'ramiz. Hozircha qadamlarni ko'z bilan kuzating:
3.2 new ichidan: o'zimizning yangi
To'rt qadamni bilsak, new ni oddiy funksiya bilan o'zimiz yoza olamiz. Kerakli hamma vosita tanish: Object.create (1- va 2-qadam birdan), call (3-qadam) va rest/spread:
function yangi(Konstruktor, ...argumentlar) {
// 1 va 2: prototipi Konstruktor.prototype bo'lgan bo'sh obyekt
const obyekt = Object.create(Konstruktor.prototype);
// 3: funksiyani shu obyektni this qilib chaqiramiz
const natija = Konstruktor.call(obyekt, ...argumentlar);
// 4: funksiya o'zi obyekt qaytarsa — o'shani, aks holda yangisini
if (typeof natija === "object" && natija !== null) {
return natija;
}
return obyekt;
}
function Taom(nom, narx) {
this.nom = nom;
this.narx = narx;
}
const choy = yangi(Taom, "Ko'k choy", 5000);
console.log(choy); // Taom { nom: "Ko'k choy", narx: 5000 }
console.log(Object.getPrototypeOf(choy) === Taom.prototype); // trueNatija haqiqiy new niki bilan bir xil. Endi new siz uchun "sehrli so'z" emas — uch qatorlik algoritm.
3.3 4-qadamning nozik joyi
To'rtinchi qadamda shart bor: "funksiya boshqa obyekt qaytarmasa". Konstruktor return bilan obyekt qaytarsa, new yangi obyektni tashlab yuboradi. Primitiv (son, satr) qaytarsa — e'tiborsiz qoldiradi:
function Birinchi() {
this.a = 1;
return { b: 2 };
}
function Ikkinchi() {
this.a = 1;
return 5;
}
console.log(new Birinchi()); // { b: 2 }
console.log(new Ikkinchi()); // Ikkinchi { a: 1 }Amalda konstruktorga return yozilmaydi. Lekin buni bilish ikki joyda foydali: eski kutubxonalar kodini o'qiganda va o'zingiz bexosdan return yozib qo'yganingizda.
Tekshirib ko'ring:
yangifunksiyasidaginatija !== nulltekshiruvi nega kerak?
Javob
typeof null — "object" (typeof darsidagi mashhur g'alatilik). Tekshiruvsiz konstruktor return null; qilsa, yangi null qaytarib yuborardi. Haqiqiy new esa null ni obyekt deb hisoblamaydi va yangi obyektni qaytaradi.
4. F.prototype — nusxalar uchun prototip
4.1 Har funksiyada bor
Har oddiy funksiya yaratilganda JavaScript unga avtomatik ravishda prototype degan xususiyat qo'shadi. Unda bitta obyekt turadi, u obyektda esa bitta xususiyat — constructor, funksiyaning o'ziga havola:
function Taom(nom, narx) {
this.nom = nom;
this.narx = narx;
}
const nomlar = Object.getOwnPropertyNames(Taom);
console.log(nomlar); // [ 'length', 'name', 'prototype' ]
console.log(Taom.prototype.constructor === Taom); // trueObject.getOwnPropertyNames — Object.keys ning qarindoshi: u sanalmaydigan kalitlarni ham ko'rsatadi (Xususiyat deskriptorlari). prototype ni Object.keys(Taom) ko'rsatmasdi.
Taom.prototype dagi obyekt — new Taom(...) bilan yasaladigan nusxalar uchun tayyorlangan prototip. new ning 2-qadami aynan shu: yangi obyektning [[Prototype]] i — Taom.prototype.
Arrow funksiya va metod shorthand'da prototype yo'q. Shuning uchun ularni new bilan chaqirib bo'lmaydi:
const Taom = (nom) => {
this.nom = nom;
};
new Taom("Osh");TypeError: Taom is not a constructorTarjimasi: "Taom — konstruktor emas". this: to'rt qoida darsida arrow'da o'z this yo'qligini ko'rgan edik. Endi ikkinchi sababi ham ma'lum: prototype ham yo'q — new 2-qadamni bajara olmaydi.
4.2 prototype va [[Prototype]] — eng ko'p chalkashtiriladigan juftlik
O'tgan darsning «Ko'p uchraydigan xatolar» bo'limida osh.prototype — undefined edi va "bu boshqa narsa" degan edik. Endi aniq farqlaymiz:
[[Prototype]] |
F.prototype |
|
|---|---|---|
| Kimda bor | har obyektda | faqat oddiy funksiyalarda |
| Nima | o'z prototipiga havola | nusxalari oladigan prototip |
| Qanday o'qiladi | Object.getPrototypeOf(x) |
F.prototype |
Eng muhim nozik joy: Taom.prototype — Taom funksiyasining o'z prototipi emas!
function Taom() {}
const ozPrototipi = Object.getPrototypeOf(Taom);
console.log(ozPrototipi === Function.prototype); // true
console.log(ozPrototipi === Taom.prototype); // falseTaom — funksiya, uning o'z [[Prototype]] i — Function.prototype (shuning uchun unda call va bind bor). Taom.prototype esa — nusxalar uchun "sovg'a": u funksiyaning o'ziga emas, new Taom() bilan tug'iladigan obyektlarga beriladi. Nomlari bir xil bo'lgani — tarixiy noqulaylik. Shuning uchun matnda doim aniq ayting: "Taom.prototype" yoki "osh ning prototipi".
Sxemada strelkalar yozuvini o'qing:
flowchart BT
OSH["osh<br/>nom, narx"]
MANTI["manti<br/>nom, narx"]
TP["Taom.prototype<br/>chekQatori"]
OSH -- "[[Prototype]]" --> TP
MANTI -- "[[Prototype]]" --> TP
TP -- "[[Prototype]]" --> OP["Object.prototype"]
OP --> N["null"]
T["Taom (funksiya)"] -- ".prototype" --> TP
TP -- ".constructor" --> Tosh va manti ning o'z ma'lumotlari — o'zida. Umumiy metod — bitta Taom.prototype da. Taom va Taom.prototype bir-biriga ikki tomonlama havola bilan bog'langan.
5. Metodlarni prototipga qo'yish
5.1 Bitta metod — hamma uchun
Endi «Nega bu kerak?» bo'limidagi uchinchi muammoni hal qilamiz:
function Taom(nom, narx) {
this.nom = nom;
this.narx = narx;
}
Taom.prototype.chekQatori = function () {
return `${this.nom}: ${this.narx} so'm`;
};
const osh = new Taom("Osh", 35000);
const manti = new Taom("Manti", 30000);
console.log(osh.chekQatori()); // Osh: 35000 so'm
console.log(manti.chekQatori()); // Manti: 30000 so'm
console.log(osh.chekQatori === manti.chekQatori); // truetrue — endi chekQatori bitta. osh.chekQatori() chaqirilganda qidiruv osh da topmaydi, Taom.prototype da topadi (prototip zanjiri). Chaqiruv esa nuqta bilan — this — osh (1-qoida). Ikki dars birlashdi: metod zanjirdan topiladi, this esa chaqiruvdan.
40 taom — bitta funksiya. 10 000 taom — baribir bitta. Fabrikada esa 10 000 ta bo'lardi.
Metod function bilan yozilgani tasodif emas. Arrow bilan yozilsa, this prototipga qo'yilgan joydagi this bo'lardi — faylning eng yuqori darajasidagi. Modulda u undefined, brauzer skriptida window — ikkalasida ham nom yo'q:
function Taom(nom) {
this.nom = nom;
}
Taom.prototype.nomi = () => this?.nom;
console.log(new Taom("Osh").nomi()); // undefinedQoida o'zgarmadi: metod — function (yoki shorthand), ichidagi callback — arrow.
5.2 Ma'lumot — o'zida, metod — prototipda
Konstruktor har chaqiruvda ishlaydi va this — har safar yangi obyekt. Demak har obyektga xos ma'lumot — ayniqsa massiv va obyektlar — konstruktorda yoziladi. O'tgan darsdagi "umumiy massiv" tuzog'i shu bilan yo'qoladi:
function Buyurtma(stol) {
this.stol = stol;
this.taomlar = [];
}
Buyurtma.prototype.qosh = function (nom) {
this.taomlar.push(nom);
};
const b1 = new Buyurtma(1);
const b5 = new Buyurtma(5);
b1.qosh("Osh");
b5.qosh("Manti");
console.log(b1.taomlar, b5.taomlar); // [ 'Osh' ] [ 'Manti' ]Har new Buyurtma da this.taomlar = [] qaytadan bajarildi — har buyurtmaning o'z massivi. qosh esa bitta, prototipda. Bu — konstruktor bilan ishlashning asosiy qolipi:
| Nima | Qayerga | Nega |
|---|---|---|
Ma'lumot (nom, taomlar) |
konstruktorda, this.x = ... |
har obyektda o'zgacha |
Metodlar (qosh, chekQatori) |
F.prototype.x = function |
hamma uchun bir xil |
5.3 Prototip jonli — keyin qo'shilgan metod ham ishlaydi
Prototipga metodni nusxalar yaratilgandan keyin qo'shsangiz ham, ular uni ko'radi:
function Taom(nom, narx) {
this.nom = nom;
this.narx = narx;
}
const manti = new Taom("Manti", 30000);
Taom.prototype.aksiyaNarxi = function (foiz) {
return this.narx - (this.narx * foiz) / 100;
};
console.log(manti.aksiyaNarxi(10)); // 27000manti aksiyaNarxi dan oldin yaratilgan, lekin u prototipning havolasini saqlaydi — nusxasini emas (Prototip jonli).
Tekshirib ko'ring:
Buyurtmakonstruktoridathis.taomlar = []o'rnigaBuyurtma.prototype.taomlar = [];yozilsa, nima bo'ladi?
Javob
Barcha buyurtmalar bitta massivni bo'lishadi: b1.qosh("Osh") dan keyin b5.taomlar da ham Osh paydo bo'ladi. this.taomlar.push — avval o'qish, o'qish esa prototipdagi umumiy massivni topadi. O'tgan darsdagi tuzoqning aynan o'zi. Massiv har obyektga konstruktorda berilishi kerak.
6. constructor xususiyati
6.1 Nusxa o'z konstruktorini "biladi"
Taom.prototype da avtomatik constructor bor edi. U zanjir orqali har nusxaga ko'rinadi:
function Taom(nom, narx) {
this.nom = nom;
this.narx = narx;
}
const osh = new Taom("Osh", 35000);
console.log(osh.constructor === Taom); // true
console.log(Object.hasOwn(osh, "constructor")); // false
const lagmon = new osh.constructor("Lag'mon", 28000);
console.log(lagmon); // Taom { nom: "Lag'mon", narx: 28000 }osh.constructor — osh ning o'zida emas, prototipdan. U orqali "xuddi shu turdagi yangi obyekt"ni konstruktor nomini bilmasdan ham yasash mumkin. Node Taom { ... } deb yozganda ham shu ma'lumotdan foydalanadi.
Tekshirib ko'ring:
osh.constructor.namenima qaytaradi?thisyo'qolishi darsidasetTimeoutichidagithis.constructor.namenegaTimeoutbergan edi?
Javob
"Taom" — osh.constructor — Taom funksiyasi, funksiyaning name xususiyati esa uning nomi. O'sha darsdagi this ham shu yo'l bilan "o'zini tanitgan": Node taymer obyektlarini Timeout konstruktori bilan yasaydi, shuning uchun uning constructor.name — "Timeout".
6.2 Tuzoq: prototype ni butunlay almashtirish
Metodlarni bittalab qo'shish o'rniga, ko'pincha butun obyekt yoziladi:
function Taom(nom) {
this.nom = nom;
}
Taom.prototype = {
chekQatori() {
return this.nom;
},
};
const osh = new Taom("Osh");
console.log(osh.chekQatori()); // Osh
console.log(osh.constructor === Taom); // false
console.log(osh.constructor === Object); // trueMetod ishladi, lekin constructor yo'qoldi. Biz avtomatik Taom.prototype ni yangi oddiy obyekt bilan almashtirdik — eski obyektdagi constructor u bilan birga ketdi. Endi osh.constructor zanjir bo'ylab Object.prototype gacha borib, Object ni topdi.
Tuzatish: metodlarni bittalab qo'shing (Taom.prototype.chekQatori = ...) yoki almashtirilgan obyektga constructor: Taom ni qo'lda yozing. Ikkinchi usulda bitta farq qoladi: qo'lda yozilgan constructor "sanaladigan" bo'ladi va for...in da chiqadi.
7. new siz chaqirish
7.1 Xato yoki jim buzilish
Konstruktor — oddiy funksiya, uni new siz ham chaqirsa bo'ladi. Unda 4-qoida emas, 2-qoida ishlaydi — this yangi obyekt bo'lmaydi:
"use strict";
function Taom(nom) {
this.nom = nom;
}
const osh = Taom("Osh");TypeError: Cannot set properties of undefined (setting 'nom')Tarjimasi: "undefined ga xususiyat yozib bo'lmaydi (nom ni yozishda)". Strict rejimda (va har modulda) this — undefined. Bu yaxshi holat: xato darhol ko'rinadi. Eski uslubdagi skriptda esa ancha yomon:
function Taom(nom) {
this.nom = nom;
}
const osh = Taom("Osh");
console.log(osh, globalThis.nom); // undefined OshXato yo'q. this — global obyekt, demak nom global o'zgaruvchi bo'lib qoldi. osh esa undefined: funksiya hech narsa qaytarmadi va new yo'q edi. Konstruktor nomini katta harf bilan yozish kelishuvi aynan shu xatoning oldini olish uchun paydo bo'lgan — Taom(...) ni ko'rgan odam "bu yerda new yetishmayapti" deb seza oladi.
7.2 new.target bilan himoya
Funksiya ichida maxsus new.target ifodasi bor: funksiya new bilan chaqirilgan bo'lsa — funksiyaning o'zi, aks holda — undefined. U bilan "unutilgan new" ni o'zimiz qo'yib qo'yamiz:
function Taom(nom) {
if (!new.target) {
return new Taom(nom);
}
this.nom = nom;
}
console.log(Taom("Osh")); // Taom { nom: 'Osh' }
console.log(new Taom("Manti")); // Taom { nom: 'Manti' }new siz chaqiruvda funksiya o'zini new bilan qayta chaqirib, natijani qaytardi. Ikkinchi yo'l — xato tashlash: "konstruktorni new bilan chaqiring". Xato tashlashni throw va Error darsida o'rganamiz.
7.3 O'rnatilgan konstruktorlar
JavaScript'ning o'z konstruktorlari bu vaziyatda har xil yo'l tutadi:
console.log(typeof Date(), typeof new Date()); // string object
console.log(Array(3)); // [ <3 empty items> ]
console.log(new Array(3)); // [ <3 empty items> ]Date() new siz — sanani satr qilib qaytaradi, new Date() esa sana obyektini. Array esa ikkala holatda bir xil ishlaydi — ichida new.target ga o'xshash tekshiruv bor. Massiv yaratish darsidagi new Array(3) va'dasi shu: new — Array konstruktorini chaqirib, yangi massiv obyektini yasaydi. Bitta son argument esa "elementlar" emas, uzunlik deb tushuniladi — shuning uchun 3 ta bo'sh joy. Bu tuzoq tufayli massivni literal ([]) yoki Array.of bilan yarating.
8. Klassga ko'prik
Konstruktor funksiya + F.prototype ga metodlar — 2015-yilgacha JavaScript'da obyektlar "turi"ni yasashning asosiy yo'li edi. Hozir buning qisqa va xavfsizroq yozuvi bor — class. U class sintaksisi darsida keladi. Ichkarida esa aynan shu dars mexanizmi ishlaydi: klass — konstruktor funksiya, klass metodlari — uning prototype ida. Bundan tashqari, klassni new siz chaqirib bo'lmaydi — darhol xato beradi. Shu tufayli bugungi «new siz chaqirish» muammosi klasslarda yo'q.
Bugungi bilim behuda emas. Klassning ichini — class ichidan darsini — aynan shu dars ustiga quramiz. Eski kutubxonalar va ko'p tayyor kod esa hamon konstruktor funksiyalar bilan yozilgan.
9. Ko'p uchraydigan xatolar
9.1 new ni unutish
«new siz chaqirish» bo'limidagi ikki holat: modulda TypeError: Cannot set properties of undefined, eski skriptda — jim global o'zgaruvchi. Tuzatish: new yozing; himoya kerak bo'lsa — new.target.
9.2 Arrow konstruktor yoki arrow metod
const Taom = (nom) => { ... } — TypeError: Taom is not a constructor. Taom.prototype.nomi = () => this.nom — jim undefined. Tuzatish: konstruktor ham, prototip metodi ham — oddiy function.
9.3 Massivni prototipga qo'yish
«Ma'lumot — o'zida, metod — prototipda» qoidasi buzilsa, nusxalar bitta massivni bo'lishadi. Tuzatish: massiv va obyektlarni konstruktorda this.x = [] bilan yarating.
9.4 prototype ni almashtirib constructor ni yo'qotish
«Tuzoq: prototype ni butunlay almashtirish» bo'limi. Xato xabari yo'q, faqat osh.constructor — Object. Tuzatish: metodlarni bittalab qo'shing.
9.5 osh.prototype ga metod qo'shish
function Taom(nom) {
this.nom = nom;
}
const osh = new Taom("Osh");
osh.prototype.chekQatori = function () {};TypeError: Cannot set properties of undefined (setting 'chekQatori')osh — nusxa, unda prototype xususiyati yo'q (undefined). prototype — faqat funksiyada. Tuzatish: Taom.prototype.chekQatori = ....
10. Mashqlar
1-mashq (oson): Stol
«Bahor» stollari uchun Stol(raqam, orinlar) konstruktorini yozing. Har stolda band xususiyati bo'lsin, boshida false. Prototipga tavsif() metodini qo'shing: 5-stol, 4 o'rin, bo'sh (band bo'lsa — band). Ikki stol yasab, birini band qiling va ikkalasining tavsifini chiqaring.
Yechim
function Stol(raqam, orinlar) {
this.raqam = raqam;
this.orinlar = orinlar;
this.band = false;
}
Stol.prototype.tavsif = function () {
const holati = this.band ? "band" : "bo'sh";
return `${this.raqam}-stol, ${this.orinlar} o'rin, ${holati}`;
};
const stol5 = new Stol(5, 4);
const stol1 = new Stol(1, 6);
stol5.band = true;
console.log(stol5.tavsif()); // 5-stol, 4 o'rin, band
console.log(stol1.tavsif()); // 1-stol, 6 o'rin, bo'shband — har stolga xos holat, shuning uchun konstruktorda. tavsif — hamma stol uchun bir xil, shuning uchun prototipda.
2-mashq (o'rta): Buyurtma va jami summa
Buyurtma(stol) konstruktorini yozing: har buyurtmaning o'z taomlar massivi bo'lsin. Prototipga ikki metod qo'shing: qosh(nom, narx) — taomni { nom, narx } obyekti sifatida qo'shadi; jami() — narxlar yig'indisini qaytaradi (reduce). 1-stolga osh va ko'k choy, 5-stolga manti qo'shib, ikkalasining jamisini chiqaring.
Yechim
function Buyurtma(stol) {
this.stol = stol;
this.taomlar = [];
}
Buyurtma.prototype.qosh = function (nom, narx) {
this.taomlar.push({ nom, narx });
};
Buyurtma.prototype.jami = function () {
return this.taomlar.reduce((jami, t) => jami + t.narx, 0);
};
const b1 = new Buyurtma(1);
const b5 = new Buyurtma(5);
b1.qosh("Osh", 35000);
b1.qosh("Ko'k choy", 5000);
b5.qosh("Manti", 30000);
console.log(b1.jami(), b5.jami()); // 40000 30000jami ichidagi reduce callback'i — arrow, lekin u this ni ishlatmaydi. Agar ishlatganida ham, arrow jami ning this ini olardi — to'g'ri natija. Har buyurtmaning o'z massivi bor, shuning uchun summalar aralashmadi.
3-mashq (qiyin): Nechta taom yasaldi?
Taom(nom, narx) konstruktori har chaqiruvda umumiy hisoblagichni oshirsin. Hisoblagich Taom funksiyasining o'zida tursin: Taom.soni (funksiya ham obyekt — IIFE va funksiya obyekt sifatida). Har taomga tartib raqami — raqam ham bersin. Uchta taom yasab, Taom.soni va oxirgi taomning raqam ini chiqaring.
Ishora: Taom.soni = 0; ni konstruktordan tashqarida bir marta yozing. Konstruktor ichida this emas, Taom ni ishlating — hisoblagich nusxaga emas, funksiyaga tegishli.
Yechim
function Taom(nom, narx) {
Taom.soni++;
this.raqam = Taom.soni;
this.nom = nom;
this.narx = narx;
}
Taom.soni = 0;
new Taom("Osh", 35000);
new Taom("Manti", 30000);
const choy = new Taom("Ko'k choy", 5000);
console.log(Taom.soni); // 3
console.log(choy.raqam); // 3
console.log(Object.hasOwn(choy, "soni")); // falseUchta joyni farqlang: raqam — har nusxada (konstruktorda this ga), metodlar — Taom.prototype da, umumiy hisoblagich — Taom funksiyasining o'zida. Nusxa soni ni ko'rmaydi: Taom funksiyasi uning prototip zanjirida emas — zanjirda Taom.prototype bor. Klasslarda bu uchinchi joy static deb ataladi (Getter/setter va static).
4-mashq: Mashqlar papkasi — «Bahor» menyusi konstruktor bilan
Bu dars mavzusi vazifalar ga hozir to'g'ri tushmaydi: vazifa obyektlari u yerda oddiy literal bo'lib qoladi, ularni class sintaksisi darsida Vazifa klassiga aylantiramiz. Shuning uchun bu qadam kurs/mashqlar/10/ papkasida bajariladi.
kurs/mashqlar/10/32-menyu/menyu.mjs faylini yarating:
Taom(nom, narx)konstruktori; har taomda o'zteglarmassivi (boshida bo'sh).- Prototipda uchta metod:
tegQosh(teg),chekQatori()—Osh: 35000 so'm [issiq](teg bo'lmasa — qavssiz),aksiyaNarxi(foiz). - To'rt taomli menyu (narxlar — «Bahor» kanoni), oshga
issiqtegini qo'shing va chekni chiqaring. - Oxirida isbotlang: metod bitta, teglar massivi esa har taomda alohida.
node menyu.mjs bilan ishga tushiring.
Yechim
function Taom(nom, narx) {
this.nom = nom;
this.narx = narx;
this.teglar = [];
}
Taom.prototype.tegQosh = function (teg) {
this.teglar.push(teg);
};
Taom.prototype.chekQatori = function () {
const teglar = this.teglar.length
? ` [${this.teglar.join(", ")}]`
: "";
return `${this.nom}: ${this.narx} so'm${teglar}`;
};
Taom.prototype.aksiyaNarxi = function (foiz) {
return this.narx - (this.narx * foiz) / 100;
};
const menyu = [
new Taom("Osh", 35000),
new Taom("Lag'mon", 28000),
new Taom("Manti", 30000),
new Taom("Ko'k choy", 5000),
];
const [osh, lagmon] = menyu;
osh.tegQosh("issiq");
menyu.forEach((taom) => console.log(taom.chekQatori()));
console.log(osh.aksiyaNarxi(10));
console.log(osh.chekQatori === lagmon.chekQatori);
console.log(osh.teglar === lagmon.teglar);Konsolda:
Osh: 35000 so'm [issiq]
Lag'mon: 28000 so'm
Manti: 30000 so'm
Ko'k choy: 5000 so'm
31500
true
falseforEach callback'i arrow — u taom.chekQatori() ni nuqta bilan chaqiradi, this yo'qolmaydi. Agar menyu.forEach(Taom.prototype.chekQatori) deb yozilganida — this yo'qolishi darsidagi xato bo'lardi. Oxirgi ikki qator darsning asosiy qoidasini isbotlaydi: metod — bitta (true), holat — har birida o'zi (false).
Bu faylni saqlab qo'ying. class sintaksisi darsida Taom konstruktorini klass bilan qayta yozib, ikki yozuvni yonma-yon solishtiramiz — keyin bu faylni ham o'zingiz klassga o'tkaza olasiz.
11. Real ishda
- Eski kod. 2015-yilgacha yozilgan kutubxonalar (jQuery'ning ichi ham) — konstruktor funksiya va
F.prototype.metod = functionbilan to'la. Ularni o'qish va tuzatish uchun bu dars kerak. - O'rnatilgan obyektlar.
new Date(),new Map(),new URL(...),new Error(...)— hammasi shu mexanizm.newdan keyin keladigan har nom — konstruktor. - Klasslar. Zamonaviy kodda yangi "tur" klass bilan yoziladi. Lekin klass xatolarini tushunish uchun uning ostidagi konstruktor va prototipni bilish kerak — intervyuda aynan shu so'raladi.
- Intervyu. "
newqanday ishlaydi?" (to'rt qadam), "newni o'zingiz yozing" (yangifunksiyasi), "prototypeva__proto__farqi?" — klassik savollar.
Xulosa
- Konstruktor funksiya —
newbilan chaqiriladigan oddiy funksiya; nomi katta harf bilan, ot shaklida. new F(...)to'rt qadami: bo'sh obyekt → prototipiF.prototype→Fni shu obyektnithisqilib chaqirish → (boshqa obyekt qaytmasa) yangi obyektni qaytarish.F.prototype— nusxalar oladigan prototip,Fning o'z prototipi emas. Undaconstructorfunksiyaning o'ziga qaraydi.- Ma'lumot — konstruktorda
this.x = ..., metodlar —F.prototype.x = functionda. Metod bitta, holat — har nusxada. - Arrow va metod shorthand konstruktor bo'la olmaydi.
prototypeni butunlay almashtirsangiz,constructoryo'qoladi. newsiz chaqiruv: moduldaTypeError, eski skriptda jim global. Himoya —new.target; to'liq yechim —class.
Keyingi dars: Object.create, prototipal meros va instanceof — obyektni boshqa obyektdan to'g'ridan-to'g'ri meros qilib yasash, instanceof ichidan qanday ishlashi va Object.create(null) lug'ati.
Manbalar
- MDN: "new" operator — "Description" bo'limi (to'rt qadam) — developer.mozilla.org
- MDN: "Object.prototype.constructor", "new.target"
- ECMAScript 2025 Language Specification: "EvaluateNew", "OrdinaryCreateFromConstructor" — tc39.es/ecma262
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!