Prototype va Prototype Chain
Muammodan boshlaylik
Siz hech toString() metodi yozmadingiz. Lekin har qanday ob'ektda ishlaydi:
const foydalanuvchi = { ism: "Jasur", yosh: 25 };
console.log(foydalanuvchi.toString()); // "[object Object]"
console.log(foydalanuvchi.hasOwnProperty("ism")); // true
toString, hasOwnProperty — bular qayerdan keldi? Siz yozmadingiz. JavaScript qayerdan topdi?
Javob — Prototype.
Prototype nima?
Har bir JavaScript ob'ekti yashirin [[Prototype]] xususiyatiga ega. Bu — "agar bu ob'ektda topilmasa, qayerdan qidirish kerak" degan ko'rsatkich.
Hayotiy o'xshatma
Tasavvur qiling: o'g'il o'z cho'ntagida qalam qidirdi — yo'q. Otasining cho'ntagiga qaradi — bor. Ishlatdi. Otasi o'z qalamini yozmagan, lekin o'g'il foydalana oldi.
JavaScript ham xuddi shunday: ob'ektda xususiyat topilmasa — uning prototypi da qidiradi. U yerda ham yo'q bo'lsa — prototypining prototypida. Bu — Prototype Chain (zanjir).
foydalanuvchi ob'ekti
↓ topilmadi
foydalanuvchi.__proto__ (Object.prototype)
↓ topilsa — ishlaydi
↓ topilmasa
null ← zanjir tugadi, undefined qaytaradi
Prototype zanjiri qanday ishlaydi?
const foydalanuvchi = { ism: "Jasur" };
// foydalanuvchi da "toString" yo'q
// JavaScript foydalanuvchi.__proto__ ga qaradi
// U yerda — Object.prototype
// Object.prototype da "toString" bor — ishlatildi
console.log(foydalanuvchi.toString()); // "[object Object]"
Vizual:
foydalanuvchi = { ism: "Jasur" }
│
│ __proto__
▼
Object.prototype = {
toString: function() {...},
hasOwnProperty: function() {...},
valueOf: function() {...},
...
}
│
│ __proto__
▼
null ← zanjir tugadi
Object.prototype — barcha oddiy ob'ektlarning "ota-onasi". toString, hasOwnProperty o'sha yerda.
Prototipni o'rnatish
Object.create — prototypi belgilangan ob'ekt yaratadi:
const hayvon = {
nafas() {
console.log("nafas olmoqda...");
}
};
const it = Object.create(hayvon); // it ning prototypi = hayvon
it.ism = "Baxter";
it.nafas(); // "nafas olmoqda..." ← hayvon dan olindi
console.log(it.ism); // "Baxter" ← o'zida bor
it = { ism: "Baxter" }
│
│ __proto__
▼
hayvon = { nafas: function }
│
│ __proto__
▼
Object.prototype
hasOwnProperty — o'zidami yoki zanjirdami?
const hayvon = { nafas() {} };
const it = Object.create(hayvon);
it.ism = "Baxter";
console.log(it.hasOwnProperty("ism")); // true ← o'zida
console.log(it.hasOwnProperty("nafas")); // false ← prototypidan
console.log("nafas" in it); // true ← zanjirda qidiradi
in operatori — zanjirni ham tekshiradi. hasOwnProperty — faqat o'zini.
Massiv va funksiyalar ham prototype zanjirida
Massivlar ham xuddi shunday. Siz map, filter, push yozmadingiz — bular Array.prototype da:
const arr = [1, 2, 3];
console.log(arr.__proto__ === Array.prototype); // true
// arr da "map" yo'q
// JavaScript arr.__proto__ (Array.prototype) ga qaradi
// Array.prototype da "map" bor — ishlatildi
arr.map(n => n * 2); // [2, 4, 6]
arr = [1, 2, 3]
│
│ __proto__
▼
Array.prototype = {
map: function() {...},
filter: function() {...},
push: function() {...},
...
}
│
│ __proto__
▼
Object.prototype
│
│ __proto__
▼
null
Prototypni o'zgartirish — ehtiyotkorlik bilan
Prototypga metod qo'shish mumkin — barcha ob'ektlarda ishlaydi:
Array.prototype.ikkilash = function() {
return this.map(n => n * 2);
};
[1, 2, 3].ikkilash(); // [2, 4, 6]
Lekin bu xavfli:
// Agar kimdir for...in bilan massivni aylansa:
const arr = [1, 2, 3];
for (const key in arr) {
console.log(key); // "0", "1", "2", "ikkilash" ← kutilmagan!
}
Array.prototype, Object.prototype ni o'zgartirish — katta loyihalarda kutilmagan xatolarga olib keladi. Polyfill yozayotgan bo'lmasangiz — qilmang.
Tez-tez uchraydigan xatolar
__proto__ ni to'g'ridan-to'g'ri o'zgartirish:
const ob = {};
ob.__proto__ = { salom() { console.log("Salom!"); } };
ob.salom(); // ishlaydi, lekin...
__proto__ ni to'g'ridan-to'g'ri o'zgartirish — sekin va xavfli. Buning o'rniga Object.create yoki class ishlatiladi.
for...in zanjirni ham ko'radi:
const ota = { merosXususiyat: true };
const bola = Object.create(ota);
bola.ozXususiyat = true;
for (const kalit in bola) {
console.log(kalit); // "ozXususiyat", "merosXususiyat" ← ikkisi ham
}
// Faqat o'zini:
for (const kalit in bola) {
if (bola.hasOwnProperty(kalit)) {
console.log(kalit); // "ozXususiyat"
}
}
Xulosa
Prototype — ob'ektning "ota-onasi". Xususiyat topilmasa — u yerda qidiriladi.
Prototype Chain — bir-biriga ulangan prototyplar zanjiri. Oxiri null.
Barcha oddiy ob'ektlar Object.prototype dan meros oladi — shuning uchun toString, hasOwnProperty hammada bor.
Massivlar Array.prototype dan meros oladi — map, filter, push o'sha yerda.
ob'ekt → Object.prototype → null
massiv → Array.prototype → Object.prototype → null
Keyingi dars
28-dars: Constructor funksiyalar