2.5-bob: this, prototype va prototypal inheritance (chuqur)
2-QISM — JavaScript (0 dan chuqurgacha) · 5-mavzu
1. Kirish va motivatsiya
Closure 2.4-bob dan keyin — JS'ning ikkinchi "sirli" juftligi: this va prototype. Bular ko'p dasturchini chalkashtiradi, chunki ular boshqa tillardan (Java, C++) farq qiladi. Lekin ularni tushunmasdan OOP 2.10-bob, class, va butun JS obyekt tizimini bilib bo'lmaydi.
this— funksiya ichida "men kim uchun ishlayapman?" degan savolning javobi. Eng chalkashi:thisfunksiya qayerda yozilganiga emas, qanday chaqirilganiga bog'liq.- Prototype — JS'ning meros (inheritance) mexanizmi. JS'da
classlar 2.10-bob aslida prototype ustiga qurilgan "shirin yuza" (syntactic sugar).
O'xshatish (
this):this— bu "hozir gaplashayotgan odam". Telefonda "men keldim" desang, "men" — gapiruvchiga bog'liq. Funksiyadathisham shunday: kim chaqirsa, o'shanga ishora qiladi.
Bu bob — JS obyekt tizimining ildizi. OOP 2.10-bob, class, React (eski class komponentlar), va ko'p kutubxonaning ichki ishlashini tushunish uchun zarur. Bu — intervyularning yana bir sevimli mavzusi.
2. Nazariya — chuqur tushuntirish
2.1. this nima?
this — funksiya chaqirilgan paytda aniqlanadigan maxsus o'zgaruvchi; u "funksiya qaysi kontekstda ishlayapti" ni bildiradi. Eng muhim qoida:
thisning qiymati funksiya QANDAY CHAQIRILGANIGA bog'liq, qayerda yozilganiga emas (arrow funksiyadan tashqari — 2.3).
Mana shu — chalkashlikning manbai. Bir xil funksiya har xil chaqirilsa, this har xil bo'ladi.
2.2. this bog'lanishining 4 qoidasi (priority bo'yicha)
thisning qiymati 4 qoidaga ko'ra aniqlanadi (yuqoridan pastga — ustunlik tartibi, MDN):
1) new binding (eng yuqori) — new bilan chaqirilsa, this — yangi yaratilgan obyekt:
function User(ism) { this.ism = ism; }
const u = new User("Ali"); // this = yangi obyekt
console.log(u.ism); // "Ali"2) Explicit binding — call/apply/bind bilan this aniq beriladi:
function salom() { return `Salom, ${this.ism}`; }
const ali = { ism: "Ali" };
salom.call(ali); // "Salom, Ali" — this = ali (2.4)3) Implicit binding — metod sifatida chaqirilsa, this — nuqtadan oldingi obyekt:
const user = {
ism: "Ali",
salom() { return `Salom, ${this.ism}`; }
};
user.salom(); // "Salom, Ali" — this = user (nuqtadan oldingi)4) Default binding (eng past) — oddiy chaqiriqda this — globalThis (yoki strict mode'da undefined):
function f() { return this; }
f(); // strict mode'da undefined; aks holda globalThis (window/global)Arrow funksiya — istisno: arrow thisni o'ziga olmaydi, balki tashqi (leksik) scope'dan meros qiladi va uni o'zgartirib bo'lmaydi (2.3, 2.4):
const obj = {
ism: "Ali",
salom: () => `Salom, ${this.ism}`, // arrow — this obj EMAS (tashqi this)
salom2() { return `Salom, ${this.ism}`; } // oddiy — this = obj
};2.3. call, apply, bind — thisni boshqarish
Bu uch metod thisni aniq belgilaydi:
function tanish(salom, belgi) {
return `${salom}, men ${this.ism}${belgi}`;
}
const ali = { ism: "Ali" };
// call — argumentlar BITTALAB
tanish.call(ali, "Salom", "!"); // "Salom, men Ali!"
// apply — argumentlar MASSIV bilan
tanish.apply(ali, ["Salom", "!"]); // "Salom, men Ali!"
// bind — DARROV chaqirmaydi, this bog'langan YANGI funksiya qaytaradi
const aliTanish = tanish.bind(ali);
aliTanish("Salom", "."); // "Salom, men Ali."| Metod | Chaqiradimi? | Argumentlar |
|---|---|---|
call |
darrov | bittalab (a, b) |
apply |
darrov | massiv ([a, b]) |
bind |
yangi funksiya | bittalab (keyin chaqiriladi) |
Esda saqlash: call = Comma (vergul bilan); apply = Array (massiv); bind = Bog'lab qo'yadi (keyin chaqirasiz).
bind— event handler va React'da (eski) juda muhim.
2.4. Prototype nima? (JS'ning meros mexanizmi)
Har bir JS obyektining yashirin havolasi bor — [[Prototype]]. Bu — boshqa obyektga havola. Obyektda xususiyat/metod topilmasa, JS uni prototypedan qidiradi — bu prototype chain (prototip zanjiri):
obj obj.[[Prototype]] ...[[Prototype]] null
(o'zida (ota prototip) (Object.prototype) (zanjir oxiri)
yo'qsa,
yuqoriga qaraydi)Bu — 2.4-dagi scope chainga o'xshash g'oya, lekin obyektlar uchun. Masalan, [].map ni chaqirsangiz — map massivning o'zida yo'q, u Array.prototypedan keladi:
const arr = [1, 2, 3];
arr.map(x => x); // map arr'da yo'q Array.prototype.map'dan topiladi[[Prototype]]ni ko'rish/o'zgartirish: Object.getPrototypeOf(obj) / Object.setPrototypeOf(); eski/de-fakto: __proto__.
2.5. Constructor function va prototype xususiyati
classdan oldin 2.10-bob, obyektlar constructor function bilan yaratilardi. Har funksiyaning prototype xususiyati bor — new bilan yaratilgan obyektlarning [[Prototype]]i shunga ishora qiladi:
function User(ism) {
this.ism = ism; // har obyektga XOS xususiyat
}
// Metodni prototype'ga qo'yamiz — barcha obyektlar ULASHADI (xotira tejaydi)
User.prototype.salom = function () {
return `Salom, ${this.ism}`;
};
const ali = new User("Ali");
const vali = new User("Vali");
ali.salom(); // "Salom, Ali" — salom prototype'dan (2.4: chain)
vali.salom(); // "Salom, Vali"
// ali va vali BITTA salom funksiyasini ulashadi (har biriga nusxa emas)Nega prototype'ga qo'yamiz? Agar
salomni har obyekt ichida yaratsak — 1000 obyekt = 1000 nusxa (0.1: RAM isrofi). Prototype'da esa — bitta nusxa, hamma ulashadi. Bu — JS'ning xotira-samarali meros usuli.
__proto__≠prototype(eng ko'p chalkashtiriladigan joy):
Fn.prototype— funksiyaning xususiyati. Bu —new Fn()bilan yaratiladigan obyektlar uchun shablon (prototip). Faqat funksiyalarda bor.obj.__proto__(ya'ni[[Prototype]]) — obyektning o'zining haqiqiy prototype'iga havolasi. Har bir obyektda bor.
newbog'lashda ular ulanadi:ali.__proto__ === User.prototype(bitta va o'sha obyekt). Ya'niprototype— funksiya tomonidagi "shablon",__proto__— instansiya tomonidagi "havola"; ularneworqali bir-biriga bog'lanadi:jsfunction User(ism) { this.ism = ism; } const ali = new User("Ali"); Object.getPrototypeOf(ali) === User.prototype; // true (ali.__proto__) User.prototype.__proto__ === Object.prototype; // true (zanjirning keyingi bo'g'ini)Amalda
__proto__ni to'g'ridan-to'g'ri ishlatmang (eski, sekin) —Object.getPrototypeOf/setPrototypeOfishlating;__proto__ni faqat tushunish uchun bilib qo'ying.
2.6. Prototypal inheritance (prototip orqali meros)
Bir obyekt boshqasidan meros olishi — prototype chain orqali:
function Hayvon(nom) { this.nom = nom; }
Hayvon.prototype.nafasOl = function () { return `${this.nom} nafas olyapti`; };
function It(nom) {
Hayvon.call(this, nom); // ota constructor'ni chaqir (this = yangi It)
}
// It.prototype'ni Hayvon.prototype'dan meros qildiramiz
It.prototype = Object.create(Hayvon.prototype);
It.prototype.constructor = It;
It.prototype.vovull = function () { return `${this.nom}: Vov!`; };
const akbar = new It("Akbar");
akbar.vovull(); // "Akbar: Vov!" (It.prototype'dan)
akbar.nafasOl(); // "Akbar nafas olyapti" (Hayvon.prototype'dan — meros!)Muhim: bu — ancha "qo'l ishi". 2.10-bobda
classsintaksisi xuddi shu narsani ancha chiroyli qiladi (class It extends Hayvon). Lekinclassichida aynan shu prototype mexanizmi ishlaydi — shuning uchun avval buni tushunish kerak.
Prototypal vs classical inheritance (JS Java/C++): Java/C++ kabi tillarda meros classical — class blueprint (chizma), obyekt esa shu blueprint'dan "qoliplangan" mustaqil nusxa; obyekt class'ga ortga havola saqlamaydi. JS'da meros prototypal — obyekt boshqa jonli obyektga (
[[Prototype]]) havola qiladi va xususiyat topilmasa runtime'da o'sha obyektga qaraydi. Shu sababli prototype'ni keyin o'zgartirsangiz (Hayvon.prototype.yangiMetod = ...), allaqachon yaratilgan barcha obyektlar darrov yangi metodni ko'radi — classical tizimda bu mumkin emas. JS'ningclassi 2.10-bob — bu prototypal mexanizm ustidagi classical-ko'rinishdagi yuza, lekin ichida baribir prototype zanjiri ishlaydi.
2.7. Prototype chain qidiruvi
Obyektda xususiyat qidirilganda (2.4-scope chain'ga o'xshash):
akbar.nafasOl ni qidirish:
1. akbar o'zida bormi? yo'q
2. It.prototype'da bormi? yo'q
3. Hayvon.prototype'da bormi? HA! (topildi)
(bo'lmasa: Object.prototype null undefined)hasOwnProperty — xususiyat obyektning o'zidami yoki prototype'danmi, tekshiradi:
akbar.hasOwnProperty("nom"); // true (o'zida)
akbar.hasOwnProperty("nafasOl"); // false (prototype'da)2.8. instanceof — zanjirda tekshirish
instanceof — obj instanceof Fn ifodasi objning prototype zanjirida Fn.prototype bor-yo'qligini tekshiradi. Ya'ni u nom emas, zanjir bo'yicha ishlaydi — yuqoridagi prototype chain qidiruvi 2.7-bob bilan bir g'oya:
akbar instanceof It; // true — It.prototype zanjirda bor
akbar instanceof Hayvon; // true — Hayvon.prototype ham zanjirda (meros!)
akbar instanceof Object; // true — Object.prototype zanjir oxirida
akbar instanceof Array; // false — Array.prototype zanjirda yo'qIchki mantig'i taxminan: Fn.prototypeni objning [[Prototype]] zanjiri bo'ylab qidiradi; topilsa true, nullga yetib topilmasa false. Shuning uchun instanceof meros bo'ylab ham true qaytaradi (akbar ham It, ham Hayvon). Solishtiring: hasOwnProperty faqat o'zini, instanceof esa butun zanjirni tekshiradi.
3. Sintaksis — tez ma'lumotnoma
// this — chaqiriqqa bog'liq (2.2)
obj.metod(); // implicit: this = obj
fn.call(obj, a, b); // explicit: this = obj (vergul)
fn.apply(obj, [a, b]); // explicit: this = obj (massiv)
const bound = fn.bind(obj); // this bog'langan yangi funksiya
new Fn(); // this = yangi obyekt
() => this // arrow: tashqi this (o'zgarmaydi)
// prototype (2.5)
function Fn() {}
Fn.prototype.metod = function () {};
Object.getPrototypeOf(obj);
Object.create(proto);
obj.hasOwnProperty("kalit"); // o'zidami? (zanjirsiz)
obj instanceof Fn; // zanjirda Fn.prototype bormi? (2.8)4. Batafsil kod namunalari
Misol 1 — thisning 4 holati (2.2)
"use strict";
function kimMan() { return this; }
// 1) default — undefined (strict)
console.log(kimMan()); // undefined
// 2) implicit — nuqtadan oldingi obyekt
const obj = { ism: "Ali", k() { return this.ism; } };
console.log(obj.k()); // "Ali"
// 3) explicit — call
console.log(kimMan.call({ x: 1 })); // { x: 1 }
// 4) new — yangi obyekt
function U(n) { this.n = n; }
console.log(new U("Vali").n); // "Vali"Misol 2 — this yo'qolishi (eng ko'p uchraydigan bug)
const user = {
ism: "Ali",
salom() { return `Salom, ${this.ism}`; }
};
const f = user.salom; // metodni "ajratib oldik"
// f(); // this endi user emas! (undefined.ism xato)
// Yechim 1: bind (2.3)
const bound = user.salom.bind(user);
console.log(bound()); // "Salom, Ali"
// Yechim 2: arrow bilan o'rash
const arrow = () => user.salom();
console.log(arrow()); // "Salom, Ali"Misol 3 — Arrow vs oddiy funksiya (this)
const taymer = {
soniya: 0,
// oddiy function — setInterval chaqirganda this yo'qoladi
notogri() {
setInterval(function () { this.soniya++; }, 1000); // this != taymer!
},
// arrow — tashqi (taymer) this'ni meros qiladi (2.2)
togri() {
setInterval(() => { this.soniya++; }, 1000); // this = taymer
}
};Misol 4 — Prototype va meros (2.5, 2.6)
function Mashina(marka) { this.marka = marka; }
Mashina.prototype.yur = function () { return `${this.marka} yuryapti`; };
const tesla = new Mashina("Tesla");
console.log(tesla.yur()); // "Tesla yuryapti" (prototype'dan)
console.log(tesla.hasOwnProperty("marka")); // true (o'zida)
console.log(tesla.hasOwnProperty("yur")); // false (prototype'da — 2.7)
console.log(Object.getPrototypeOf(tesla) === Mashina.prototype); // true
console.log(tesla instanceof Mashina); // true (zanjirda — 2.8)
console.log(tesla instanceof Object); // true (zanjir oxiri)5. To'g'ri va noto'g'ri holatlar
1) Obyekt metodida arrow function
// arrow — this obyekt EMAS (tashqi this — 2.2)
const obj = { ism: "Ali", salom: () => this.ism }; // undefined
// oddiy metod
const obj = { ism: "Ali", salom() { return this.ism; } };2) Callbackda this yo'qolishi
// oddiy function callback'da this yo'qoladi (Misol 3)
setInterval(function () { this.x++; }, 1000);
// arrow (tashqi this meros)
setInterval(() => { this.x++; }, 1000);3) Metodni ajratib olib chaqirish
// this bog'lanishi yo'qoladi (Misol 2)
const f = obj.metod; f();
// bind bilan
const f = obj.metod.bind(obj); f();4) Metodni har obyekt ichida yaratish (prototype o'rniga)
// har obyekt o'z nusxasini oladi (RAM isrofi — 2.5)
function U(n) { this.n = n; this.salom = function(){...}; }
// prototype'da bitta nusxa
function U(n) { this.n = n; }
U.prototype.salom = function(){...};6. Keng tarqalgan xatolar va yechimlari
Xato 1 — Cannot read properties of undefined (reading 'x')
Sababi: this kutilgan obyekt emas (default/yo'qolgan binding — 2.2). Yechimi: bind, arrow, yoki metodni obj.metod() ko'rinishida chaqiring.
Xato 2 — Arrow metodda this ishlamaydi
Sababi: arrow thisni meros qiladi — obyekt metodida noto'g'ri 2.2-bob. Yechimi: obyekt metodi uchun oddiy function.
Xato 3 — TypeError: Fn is not a constructor / newni unutish
Sababi: constructor'ni newsiz chaqirdingiz (this global/undefined). Yechimi: new Fn(); (yoki class — 2.10, u himoyalaydi).
Xato 4 — Prototype metodlari topilmayapti
Sababi: Fn.prototypeni butunlay almashtirdingiz (Fn.prototype = {...}) va constructorni yo'qotdingiz 2.6-bob. Yechimi: Object.create bilan to'g'ri zanjir; yoki class ishlating.
Xato 5 — this React class komponentda undefined
Sababi: metod bind qilinmagan (eski React). Yechimi: arrow metod yoki constructor'da bind (zamonaviyda — function komponent + hook, 11.5).
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- OOP / class 2.10-bob:
class— prototype ustiga sintaksis;this— metodlarda. - Arrow funksiya (2.3, 2.4):
thisni meros qilishi — callback va React'da kalit. - Array metodlari 2.7-bob:
thiscallback'larda (arrow afzal). - DOM event 2.16-bob: handler'da
this— element; arrow bilan ehtiyot. - React (11): eski class komponentlarda
thismuammosi; function komponent buni hal qildi. - Kutubxonalar: ko'p kutubxona prototype/
thisustida (Expressreq/resmetodlari).
8. Eng yaxshi amaliyotlar (best practices)
thisni chaqiriq aniqlaydi — funksiya qanday chaqirilganini tekshiring (2.1, 2.2).- Obyekt metodiga oddiy
function, callbackga arrow 2.2-bob. thisyo'qolsa —bindyoki arrow 2.3-bob.- Metodlarni prototype'ga (yoki
classga) qo'ying, har obyekt ichida emas 2.5-bob. - Zamonaviy kodda
classishlating 2.10-bob — prototype'ni qo'lda boshqarishdan ko'ra toza. strict mode("use strict"yoki ES modul) —thisdefault'iniundefinedqiladi (xatoni erta ko'rsatadi).- Prototype mexanizmini tushuning —
class, meros, kutubxonalarni tushunish uchun. - React'da function komponent + hook ishlating —
thismuammosini umuman yo'q qiladi 11.5-bob.
9. Amaliy loyiha: "Prototype bilan OOP — classdan oldin"
class 2.10-bob dan oldin, xom prototype bilan obyekt tizimi qurib, mexanizmni chuqur his qilasiz.
Maqsad
this, constructor function, prototype va prototypal inheritance'ni amalda qo'llab, JS obyekt tizimini ichdan tushunish (keyin class "sehr" emas, "yuza" bo'lib ko'rinadi).
Talablar (requirements)
Hayvonconstructor:nom,yoshxususiyatlari;prototypedatasvir()vanafasOl()metodlari 2.5-bob.ItvaMushuk—Hayvondan meros (prototype chain — 2.6); har biri o'zovoz()metodiga ega (Vov/Miyov).thisnamoyishi: bitta metodnicall/apply/bindbilan boshqa obyektga qo'llab ko'rsating 2.3-bob.thisyo'qolishi: metodni ajratib olib chaqirib (Misol 2), muammoni vabindyechimini ko'rsating.- Arrow vs function: obyekt metodida arrow va oddiy funksiya farqini ko'rsating (Misol 3).
- Prototype tekshiruvi:
hasOwnProperty,Object.getPrototypeOfvainstanceofbilan zanjirni ko'rsating (2.7, 2.8) —it instanceof Itham,it instanceof Hayvonhamtrueekanini tasdiqlang. - (Bonus) Keyin xuddi shu tizimni
classbilan qayta yozing (2.10'ga tayyorlanish) va solishtiring.
Maslahatlar (hint)
- Meros:
It.prototype = Object.create(Hayvon.prototype)+constructorni tikla 2.6-bob. - Ota constructor'ni chaqirish:
Hayvon.call(this, nom, yosh)2.3-bob. thisyo'qolishiniconst f = it.tasvir; f()bilan ko'rsating, keyin.bind(it)bilan tuzating.hasOwnProperty— o'zidagi (true) va prototype'dagi (false) xususiyatni ajratadi.- Har metodda
thisnimaga ishora qilayotganini izohda yozing.
"Tayyor" mezonlari (acceptance criteria)
-
Hayvonconstructor + prototype metodlari ishlaydi. -
It/MushukHayvondan meros oladi (prototype chain). -
call/apply/bindnamoyish qilingan. -
thisyo'qolishi muammosi vabindyechimi ko'rsatilgan. - Arrow vs function
thisfarqi ko'rsatilgan. -
hasOwnProperty/getPrototypeOf/instanceofbilan zanjir tekshirilgan. - Kod izohlarida
thishar joyda nimaga ishora qilishi yozilgan.
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda JS obyekt tizimining ildizini — this va prototypeni o'rgandik:
this— funksiya qanday chaqirilganiga bog'liq (qayerda yozilganiga emas). 4 qoida: new > explicit (call/apply/bind) > implicit (nuqtadan oldingi) > default (undefined/global). Arrow — tashqithisni meros qiladi.call/apply/bind—thisni boshqarish (vergul / massiv / bog'lab qo'yish).- Prototype — JS'ning meros mexanizmi; prototype chain orqali xususiyat qidiruvi (2.4-scope chain'ga o'xshash).
- Constructor function +
prototype— metodlarni ulashish (xotira tejash); prototypal inheritance —Object.createbilan.__proto__(obyekt havolasi) ≠prototype(funksiya shabloni). instanceof— obyekt zanjirida berilganprototypebor-yo'qligini tekshiradi (meros bo'ylab hamtrue);hasOwnPropertyesa faqat o'zini.class2.10-bob — bularning chiroyli yuzasi (syntactic sugar); JS merosi prototypal, Java/C++ esa classical.
Keyingi bob — 2.6-bob: String va Number metodlari. Obyekt tizimini tushundik; endi kundalik ishda eng ko'p ishlatiladigan tayyor vositalarga — string va number metodlariga o'tamiz (slice, split, replace, toFixed, parseInt...). Bular matn va sonlarni qayta ishlashning amaliy quroli.
Foydalanilgan rasmiy/ishonchli manbalar
- MDN Web Docs —
this,Function.prototype.bind/call/apply - MDN Web Docs — Inheritance and the prototype chain,
Object.create/getPrototypeOf - MDN Web Docs — arrow functions va
this
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!