"prototype" xususiyati JavaScript-ning oâzi tomonidan keng qoâllaniladi. Konstruktorning barcha funktsiyalari undan foydalanadi.
Avval oddiy narsalar uchun, keyin esa murakkab narsalar uchun qanday ekanligini bilib olamiz.
Object.prototype
Aytaylik, biz boâsh obyektni chiqaramiz:
let obj = {};
alert(obj); // "[object Object]" ?
"[object Object]" massivini yaratadigan kod qayerda? Bu oârnatilgan toString usuli, ammo u qayerda? Obj boâsh!
â¦Ammo obj = {} qisqa yozuvi obj = new Object() bilan bir xil, bu yerda Object oârnatilgan konstruktor funktsiyasi boâlib, oâzining prototype ga toString bilan va boshqa usullar bilan ulkan obyektga murojaat qiladi.
Mana nima boâlmoqda:
new Object() deb nomlanganda (yoki {...} soâzma-soâz obyekti yaratiladi), uning [[Prototype]] biz muhokama qilgan qoidaga muvofiq Object.prototype ga oârnatiladi oldingi bobda muhokama qilindi:
Shunday qilib, obj.toString() deb nomlanganda usul Object.prototype dan olinadi.
Buni quyidagicha tekshirishimiz mumkin:
let obj = {};
alert(obj.__proto__ === Object.prototype); // true
alert(obj.toString === obj.__proto__.toString); //true
alert(obj.toString === Object.prototype.toString); //true
Iltimos, Object.prototype ustidagi zanjirda qoâshimcha [[Prototype]] mavjud emasligini unutmang:
alert(Object.prototype.__proto__); // null
Boshqa oârnatilgan prototiplar
Array, Date, Function va boshqa oârnatilgan narsalar ham prototiplarda usullarni saqlaydi.
Masalan, [1, 2, 3] massivini yaratganimizda, ichidagi sukut boâyicha yangi new Array() konstruktoridan foydalaniladi. Shunday qilib, massiv maâlumotlari yangi obyektga yoziladi va Array.prototype uning prototipiga aylanadi va usullarni taqdim etadi. Bu juda samarali xotira.
Spetsifikatsiya boâyicha, barcha oârnatilgan prototiplarning yuqori qismida Object.prototype mavjud. Baâzan odamlar âhamma narsa obyektlardan meros qilib oladiâ deyishadi.
Bu yerda umumiy rasm (3 ta ichki oârnatilgan boâlishi uchun):
Keling, prototiplarni qoâlda tekshiramiz:
let arr = [1, 2, 3];
// u Array.prototype-dan meros qilib oladimi?
alert(arr.__proto__ === Array.prototype); // true
// keyin Object.prototype danmi?
alert(arr.__proto__.__proto__ === Object.prototype); // true
// va tepada null.
alert(arr.__proto__.__proto__.__proto__); // null
Prototiplardagi baâzi usullar bir-biriga toâgâri kelishi mumkin, masalan, Array.prototype ning vergul bilan ajratilgan elementlarini sanab oâtadigan toString ga ega:
let arr = [1, 2, 3];
alert(arr); // 1,2,3 <-- Array.prototype.toString natijasi
Avval koârganimizdek, Object.prototype da toString mavjud, ammo Array.prototype zanjirda yaqinroq, shuning uchun massiv variantidan foydalaniladi.
Chrome-ning dasturchi konsoliga oâxshash brauzer vositalari merosni ham koârsatadi (console.dir ichki obyektlar uchun ishlatilishi kerak boâlishi mumkin):
Boshqa oârnatilgan obyektlar ham xuddi shu tarzda ishlaydi. Hatto funktsiyalar â ular oârnatilgan Function konstruktorining obyektlari va ularning usullari (call/apply va boshqalar) Function.prototype dan olingan. Funksiyalarda oâziga xos toString mavjud.
function f() {}
alert(f.__proto__ == Function.prototype); // true
alert(f.__proto__.__proto__ == Object.prototype); // true, obyektdan meros olish
Primitivlar
Eng murakkab narsa matnlar, raqamlar va mantiqiy turdagi qiymatlar bilan sodir boâladi.
Esimizda boâlganidek, ular obyekt emas. Ammo biz ularning xususiyatlariga kirishga harakat qilsak, u holda vaqtinchalik oârash moslamalari oârnatilgan String, Number, Boolean konstruktorlari yordamida yaratiladi, ular usullarni beradi va yoâqoladi.
Ushbu obyektlar biz uchun koârinmas tarzda yaratilgan va aksariyat interpretatorlar ularni optimallashtiradi, ammo spetsifikatsiya uni aynan shu tarzda tasvirlaydi. Ushbu obyektlarning usullari String.prototype, Number.prototype va Boolean.prototype kabi prototiplarda mavjud.
nullvaundefinedqiymatlarida hech qanday moslama mavjud emasMahalliy prototiplarni oâzgartirish
Mahalliy prototiplarni oâzgartirish mumkin. Masalan, String.prototype ga usul qoâshsak, u barcha matnlar uchun mavjud boâladi:
String.prototype.show = function() {
alert(this);
};
"BOOM!".show(); // BOOM!
Rivojlanish jarayonida biz xohlagan yangi oârnatilgan usullar haqida gâoyalarimiz boâlishi mumkin va ularni mahalliy prototiplarga qoâshishni xohlashimiz mumkin. Ammo bu umuman yomon fikr.
Prototiplar globaldir, shuning uchun ziddiyatni topish oson. Agar ikkita kutubxona String.prototype.show usulini qoâshsa, ulardan biri boshqasining ustiga yoziladi.
Shunday qilib, odatda, mahalliy prototipni oâzgartirish yomon fikr deb hisoblanadi.
Zamonaviy dasturlashda mahalliy prototiplarni oâzgartirishni tasdiqlaydigan bitta holat mavjud. Bu juda koâp toâldirish.
Polyfilling â bu JavaScript spetsifikatsiyasida mavjud boâlgan, ammo hozirgi JavaScript interpretatori tomonidan qoâllab-quvvatlanmagan usulning oârnini bosuvchi soâz.
Keyin biz uni qoâlda amalga oshirishimiz va u bilan oârnatilgan prototipni toâldirishimiz mumkin.
Masalan:
if (!String.prototype.repeat) {
// agar bunday usul bo'lmasa
// uni prototipga qo'shing
String.prototype.repeat = function (n) {
// matni n marta takrorlang
// aslida, kod bundan biroz murakkabroq bo'lishi kerak
// (to'liq algoritm spetsifikatsiyada)
// ammo hatto nomukammal polyfill ham ko'pincha yetarlicha yaxshi deb hisoblanadi
return new Array(n + 1).join(this);
};
}
alert("La".repeat(3)); // LaLaLa
Prototiplardan qarz olish
Dekorativlar va ekspeditorlik, call/apply bobida biz qarz olish usuli haqida suhbatlashdik.
Ana shunda biz bir obyektdan usul olib, boshqasiga koâchiramiz.
Mahalliy prototiplarning baâzi usullari koâpincha qarzga olinadi.
Masalan, agar biz massivga-oâxshash obyekt qilsak, unga baâzi bir massiv usullarni koâchirishni xohlashimiz mumkin.
Masalan:
let obj = {
0: "Hello",
1: "world!",
length: 2,
};
obj.join = Array.prototype.join;
alert( obj.join(',') ); // Hello,world!
U ishlaydi, chunki oârnatilgan join usulining ichki algoritmi faqat toâgâri indekslar va length xususiyati haqida qaygâuradi, chunki bu obyekt haqiqatan ham massiv ekanligini tekshirmaydi. Va koâplab oârnatilgan usullar shunga oâxshashdir.
Yana bir imkoniyat â obj.__proto__ ni Array.prototype ga oârnatish orqali meros olish, shunday qilib barcha Array usullari avtomatik ravishda obj da mavjud.
Ammo obj boshqa obyektdan meros boâlib qolgan boâlsa, bu mumkin emas. Esingizda boâlsa, biz bir vaqtning oâzida faqat bitta obyektdan meros olishimiz mumkin.
Qarz olish usullari moslashuvchan, agar kerak boâlsa, turli xil narsalardan funksionallikni aralashtirishga imkon beradi.
Xulosa
- Barcha oârnatilgan obyektlar bir xil shablonga amal qiladi:
- Usullar prototipda saqlanadi (
Array.prototype,Object.prototype,Date.prototype). - Obyektning oâzi faqat maâlumotlarni saqlaydi (massiv elementlari, obyekt xususiyatlari, sana).
- Usullar prototipda saqlanadi (
- Ibtidoiy usullar oârash moslamalari prototiplarida ham saqlanadi:
Number.prototype,String.prototype,Boolean.prototype. Faqatundefinedvanullda oârash moslamalari yoâq. - Oârnatilgan prototiplarni oâzgartirish yoki yangi usullar bilan toâldirish mumkin. Ammo ularni oâzgartirish tavsiya etilmaydi. Ehtimol, bu faqat bitta ruxsat etilgan sabab â biz yangi standartni qoâshganimizda, ammo hali JavaScript-ni interpretatorda tomonidan qoâllab-quvvatlanmaganimizda.
Izohlar
<code>yorlig'ini ishlating, bir nechta satrlar uchun - ularni<pre>yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepenâ¦)