WisarWisar
Dasturlash kitobi/2-QISM — JavaScript14 daqiqa

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: this funksiya 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. Funksiyada this ham 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, thisyangi yaratilgan obyekt:

js
function User(ism) { this.ism = ism; }
const u = new User("Ali");   // this = yangi obyekt
console.log(u.ism);          // "Ali"

2) Explicit bindingcall/apply/bind bilan this aniq beriladi:

js
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, thisnuqtadan oldingi obyekt:

js
const user = {
  ism: "Ali",
  salom() { return `Salom, ${this.ism}`; }
};
user.salom();   // "Salom, Ali" — this = user (nuqtadan oldingi)

4) Default binding (eng past) — oddiy chaqiriqda thisglobalThis (yoki strict mode'da undefined):

js
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):

js
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, bindthisni boshqarish

Bu uch metod thisni aniq belgilaydi:

js
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):

text
  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:

js
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:

js
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.prototypefunksiyaning 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.

new bog'lashda ular ulanadi: ali.__proto__ === User.prototype (bitta va o'sha obyekt). Ya'ni prototype — funksiya tomonidagi "shablon", __proto__ — instansiya tomonidagi "havola"; ular new orqali bir-biriga bog'lanadi:

js
function 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/setPrototypeOf ishlating; __proto__ni faqat tushunish uchun bilib qo'ying.

2.6. Prototypal inheritance (prototip orqali meros)

Bir obyekt boshqasidan meros olishi — prototype chain orqali:

js
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 class sintaksisi xuddi shu narsani ancha chiroyli qiladi (class It extends Hayvon). Lekin class ichida 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'ning classi 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):

text
  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:

js
akbar.hasOwnProperty("nom");      // true (o'zida)
akbar.hasOwnProperty("nafasOl");  // false (prototype'da)

2.8. instanceof — zanjirda tekshirish

instanceofobj 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:

js
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'q

Ichki 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

js
// 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)

js
"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)

js
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)

js
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)

js
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

js
//  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

js
//  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

js
//  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)

js
//  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: this callback'larda (arrow afzal).
  • DOM event 2.16-bob: handler'da this — element; arrow bilan ehtiyot.
  • React (11): eski class komponentlarda this muammosi; function komponent buni hal qildi.
  • Kutubxonalar: ko'p kutubxona prototype/this ustida (Express req/res metodlari).

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.
  • this yo'qolsa — bind yoki arrow 2.3-bob.
  • Metodlarni prototype'ga (yoki classga) qo'ying, har obyekt ichida emas 2.5-bob.
  • Zamonaviy kodda class ishlating 2.10-bob — prototype'ni qo'lda boshqarishdan ko'ra toza.
  • strict mode ("use strict" yoki ES modul) — this default'ini undefined qiladi (xatoni erta ko'rsatadi).
  • Prototype mexanizmini tushuningclass, meros, kutubxonalarni tushunish uchun.
  • React'da function komponent + hook ishlating — this muammosini 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)

  1. Hayvon constructor: nom, yosh xususiyatlari; prototypeda tasvir() va nafasOl() metodlari 2.5-bob.
  2. It va MushukHayvondan meros (prototype chain — 2.6); har biri o'z ovoz() metodiga ega (Vov/Miyov).
  3. this namoyishi: bitta metodni call/apply/bind bilan boshqa obyektga qo'llab ko'rsating 2.3-bob.
  4. this yo'qolishi: metodni ajratib olib chaqirib (Misol 2), muammoni va bind yechimini ko'rsating.
  5. Arrow vs function: obyekt metodida arrow va oddiy funksiya farqini ko'rsating (Misol 3).
  6. Prototype tekshiruvi: hasOwnProperty, Object.getPrototypeOf va instanceof bilan zanjirni ko'rsating (2.7, 2.8) — it instanceof It ham, it instanceof Hayvon ham true ekanini tasdiqlang.
  7. (Bonus) Keyin xuddi shu tizimni class bilan 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.
  • this yo'qolishini const f = it.tasvir; f() bilan ko'rsating, keyin .bind(it) bilan tuzating.
  • hasOwnProperty — o'zidagi (true) va prototype'dagi (false) xususiyatni ajratadi.
  • Har metodda this nimaga ishora qilayotganini izohda yozing.

"Tayyor" mezonlari (acceptance criteria)

  • Hayvon constructor + prototype metodlari ishlaydi.
  • It/Mushuk Hayvondan meros oladi (prototype chain).
  • call/apply/bind namoyish qilingan.
  • this yo'qolishi muammosi va bind yechimi ko'rsatilgan.
  • Arrow vs function this farqi ko'rsatilgan.
  • hasOwnProperty/getPrototypeOf/instanceof bilan zanjir tekshirilgan.
  • Kod izohlarida this har 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 — tashqi thisni meros qiladi.
  • call/apply/bindthisni 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 inheritanceObject.create bilan. __proto__ (obyekt havolasi) ≠ prototype (funksiya shabloni).
  • instanceof — obyekt zanjirida berilgan prototype bor-yo'qligini tekshiradi (meros bo'ylab ham true); hasOwnProperty esa faqat o'zini.
  • class 2.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!
2.5-bob: this, prototype va prototypal inheritance (chuqur) — Wisar