Prototipli meros
Dasturlashda biz ko'pincha mavjud narsani olib, uni biroz kengaytirmoqchi bo'lamiz. Masalan, bizda user obyekti bor va biz unga o'xshash, lekin qo'shimcha imkoniyatga ega admin yasashni istaymiz. Har safar hamma narsani qaytadan yozmaslik uchun JavaScript'da prototipli meros (prototypal inheritance) mavjud.
[[Prototype]] yashirin xossasi
JavaScript'dagi har bir obyektda [[Prototype]] deb nomlangan maxsus yashirin xossa bor. U yoki null ga, yoki boshqa bir obyektga ishora qiladi. O'sha ishora qilingan obyekt shu obyektning prototipi deb ataladi.
Agar biz obyektdan biror xossani o'qimoqchi bo'lsak, lekin u xossa obyektning o'zida topilmasa, JavaScript avtomatik ravishda uni prototipdan qidiradi. Dasturlashda buni "prototipli meros" deb atashadi. Ko'plab qulay til imkoniyatlari va texnikalari aynan shu mexanizmga asoslangan.
[[Prototype]] โ ichki, yashirin xossa. Biz unga to'g'ridan-to'g'ri kira olmaymiz, lekin uni o'rnatish va o'qishning bir nechta usullari bor. Ulardan biri โ eskirgan, lekin ta'lim uchun qulay __proto__.__proto__ orqali prototipni o'rnatish
[[Prototype]] ni belgilashning tarixiy usullaridan biri โ __proto__ xossasidan foydalanish. Keling, ikkita obyekt yasab, birini ikkinchisining prototipiga aylantiramiz:
Bu yerda rabbit obyektida eats xossasi yo'q. JavaScript uni topa olmagach, prototip โ animal obyektiga qaraydi va u yerdan topadi. Biz "animal โ rabbitning prototipi" yoki "rabbit prototip orqali animaldan meros oladi" deymiz.
__proto__ โ bu aslida [[Prototype]] uchun tarixiy getter/setter. U [[Prototype]] ning o'zi EMAS. Zamonaviy kodda uning o'rniga Object.getPrototypeOf va Object.setPrototypeOf ishlatiladi (bu haqda oxirgi darsda batafsil to'xtalamiz).Prototip zanjiri
Prototip yana o'z prototipiga ega bo'lishi mumkin, u ham o'zinikiga โ shu tariqa prototip zanjiri (prototype chain) hosil bo'ladi. Xossa qidirilganda JavaScript shu zanjir bo'ylab yuqoriga harakatlanadi:
Yuqoridagi longEar.walk() chaqirilganda JavaScript avval longEarda walk ni qidiradi, topmaydi; keyin rabbitdan qidiradi, u ham yo'q; oxiri animaldan topadi. Zanjir bo'ylab yuqoriga qidirish shunday ishlaydi.
__proto__ ni aylana ko'rinishida o'rnatmoqchi bo'lsak, JavaScript xato beradi. 2) __proto__ qiymati yoki obyekt, yoki null bo'lishi kerak โ boshqa turlar (masalan, son yoki satr) e'tiborsiz qoldiriladi.Yozish (write) prototipni ishlatmaydi
Prototip faqat xossani o'qishda ishlatiladi. Xossaga qiymat berish (yozish) yoki uni o'chirish amallari to'g'ridan-to'g'ri obyektning O'ZIDA bajariladi.
Ko'rib turganingizdek, rabbit.walk ga yozish animal ni o'zgartirmadi โ u faqat rabbit obyektiga yangi metod qo'shdi. Endi keyingi chaqiruvlar o'sha yangi metodni ishlatadi va prototipga umuman murojaat qilmaydi.
"this" qiymati o'zgarmaydi
Muhim savol: metod prototipdan olinsa, uning ichidagi this nimaga teng bo'ladi? Javob: this HAR DOIM nuqtadan oldingi obyektga teng bo'ladi. Metod prototipda bo'lishidan qat'i nazar, u chaqirilgan obyekt bilan ishlaydi:
Demak, metodlar umumiy (prototipda) bo'lsa-da, obyekt holati (state) esa har bir obyektning o'zida saqlanadi. Bu juda kuchli naqsh: bir necha obyekt bitta prototipdan metodlarni ulashadi, lekin har biri o'z ma'lumotlari bilan ishlaydi.
for..in va prototip xossalari
for..in sikli obyektning nafaqat o'z xossalarini, balki meros olingan (prototipdagi) xossalarini ham aylanib chiqadi. Ammo Object.keys kabi metodlar faqat obyektning O'Z xossalarini qaytaradi:
Agar bizga faqat obyektning o'z xossalari kerak bo'lsa, obj.hasOwnProperty(key) metodidan foydalanamiz โ u xossa aynan shu obyektga tegishli bo'lsa true, prototipdan meros olingan bo'lsa false qaytaradi:
hasOwnProperty ning o'zi ham qayerdandir keladi โ u Object.prototype.hasOwnProperty. Nega u for..inda chiqmaydi? Chunki tug'ma (built-in) prototip xossalari enumerable: false bayrog'iga ega, ya'ni ular sanab chiqilmaydi. Shu sababli eats va jumps chiqadi, lekin hasOwnProperty chiqmaydi.Xulosa
- JavaScript'da har bir obyektning yashirin
[[Prototype]]xossasi bor โ u boshqa obyekt yokinull; - Xossa obyektda topilmasa, u prototipdan (va prototip zanjiri bo'ylab) qidiriladi;
__proto__โ[[Prototype]]uchun tarixiy getter/setter (zamonaviy kodda undan qoching);- Xossaga yozish va uni o'chirish to'g'ridan-to'g'ri obyektning o'zida bajariladi, prototip faqat o'qishda ishlaydi;
- Metod prototipdan olinsa ham,
thischaqirilgan obyektga teng bo'ladi; for..inmeros olingan xossalarni ham aylanadi,Object.keysvahasOwnPropertyesa faqat o'z xossalarini beradi.