Funksiya bog'lash (bind)
Obyekt metodini alohida uzatganimizda โ masalan, setTimeoutga yoki hodisa (event) ishlovchisiga โ this yo'qoladi. Ushbu darsda bu klassik muammoni va uni bind orqali hal qilishni o'rganamiz.
this yo'qolishi muammosi
Obyekt metodini bir joyga uzatib, keyin boshqa kontekstda chaqirsak โ this asl obyektga emas, boshqa qiymatga ishora qiladi. Klassik misol โ metodni setTimeoutga uzatish:
let user = {
ism: "Ali",
salom() {
console.log("Salom, " + this.ism);
}
};
// this yo'qoladi:
setTimeout(user.salom, 1000);
// Natija: Salom, undefined
// (chunki setTimeout metodni obyektdan "ajratib" chaqiradi)
Nima uchun shunday bo'ladi? Chunki setTimeout user.salom funksiyasini oladi, lekin user obyektidan uzilgan holda. Chaqirilganda esa this mavjud emas (yoki brauzerda window) bo'lib qoladi.
this funksiya qanday e'lon qilinishiga emas, qanday chaqirilishiga bog'liq. user.salom() chaqirilsa this โ user; alohida func() chaqirilsa โ yo'q.Vaqtinchalik yechim: o'ram
Eng oddiy yechim โ funksiyani o'rovchi (wrapper) funksiyaga o'rab uzatish:
let user = {
ism: "Ali",
salom() {
console.log("Salom, " + this.ism);
}
};
setTimeout(function() {
user.salom(); // this endi to'g'ri โ user
}, 1000);
// Natija: Salom, Ali
setTimeout ishga tushguncha user o'zgartirilsa (masalan user = boshqaObyekt), o'ram yangi qiymatni ishlatadi. bind esa qiymatni bog'lanish vaqtida qat'iy mahkamlaydi.func.bind โ kontekstni mahkamlash
bind metodi thisni qat'iy bog'langan yangi funksiyani qaytaradi. Sintaksisi:
let bog_langan = func.bind(context);
Natijadagi bog_langan โ bu func bilan bir xil funksiya, lekin uning thisi doimo context bo'ladi, qanday chaqirilishidan qat'i nazar:
Endi setTimeout muammosi ham osongina hal bo'ladi โ bog'langan funksiyani uzatamiz:
let salomBer = user.salom.bind(user);
setTimeout(salomBer, 1000);
// Natija: Salom, Ali โ this yo'qolmaydi
obj[key] = obj[key].bind(obj) qilish mumkin. Ba'zi kutubxonalar (masalan React'ning eski kodi) shu naqshni ko'p ishlatgan.Qisman qo'llash (partial application)
bind nafaqat thisni, balki argumentlarni ham oldindan mahkamlashi mumkin. Bu qisman qo'llash (partial application) deb ataladi:
let bog_langan = func.bind(context, arg1, arg2, ...);
Argumentlardan bir qismini oldindan belgilab, faqat qolganini keyin uzatiladigan yangi funksiya olamiz:
Bu texnika mavjud umumiy funksiyadan aniqroq, ixtisoslashgan funksiyalar yasashda juda foydali. Masalan, send(from, to, text) dan sendTo(text) yasab, from va toni oldindan belgilash mumkin:
bind birinchi argumentlarni belgilaydi, keyin chaqiruv paytida berilganlar ularning davomiga qo'shiladi.bind haqida muhim jihatlar
- Bog'langan funksiyani qayta bog'lash mumkin emas โ
bindbir marta va butunlay mahkamlaydi; bindhar chaqirilganda yangi funksiya yaratadi, shuning uchun uni saqlab qo'yish kerak (ayniqsa hodisa ishlovchilarini olib tashlashda);- Bog'langan funksiyaning
namexossasi"bound "prefiksi bilan boshlanadi.
func.bind(user1).bind(user2) โ ikkinchi bind ta'sir qilmaydi! this baribir user1 bo'lib qoladi. Bog'lanish qaytarilmaydi.Xulosa
- Metodni alohida uzatganda
thisyo'qoladi โ chunki u chaqirilish usuliga bog'liq; func.bind(context)โthisi doimocontextbo'lgan yangi funksiya qaytaradi;- Bu
setTimeout, hodisa ishlovchilari va callback'larda juda foydali; func.bind(context, arg1, arg2)โ argumentlarni ham oldindan mahkamlaydi (qisman qo'llash);- Bog'langan funksiyani qayta bog'lab bo'lmaydi va u har safar yangi funksiya bo'ladi.