JavaScript'da Call, Apply va Bind Metodlarini O'zlashtirish
JavaScript'da `call()`, `apply()` va `bind()` funksiyalarning bajarilish kontekstini boshqarish imkonini beruvchi kuchli metodlardir.
So'nggi yangilanish: 2024-12-14Kirish
JavaScript'da call()
, apply()
va bind()
funksiyalarning bajarilish kontekstini boshqarish imkonini beruvchi kuchli metodlardir. Bu metodlar this
kalit so'zini manipulyatsiya qilish va funksiyalarni "qarz olish" uchun juda muhimdir. Bu metodlarni tushunish moslashuvchan va qayta ishlatiluvchi kod yozish uchun juda muhim, ayniqsa JavaScript'da obyektga yo'naltirilgan dasturlash bilan ishlashda.
Ushbu keng qamrovli qo'llanma call()
, apply()
va bind()
metodlarini tushuntirishga, ularning xatti-harakatlari, foydalanish holatlari va potensial xatolarini o'rganishga qaratilgan.
Call, Apply va Bind Haqida Umumiy Ma'lumot
call()
, apply()
va bind()
barcha JavaScript funksiyalarida mavjud bo'lgan metodlardir. Ular funksiya uchun this
qiymatini, u qanday chaqirilganidan qat'i nazar, aniq o'rnatish imkonini beradi. Qisqacha ma'lumot:
call()
: Funksiyani berilganthis
qiymati va alohida-alohida taqdim etilgan argumentlar bilan chaqiradi.apply()
: Funksiyani berilganthis
qiymati va massiv sifatida taqdim etilgan argumentlar bilan chaqiradi.bind()
: Qanday chaqirilishidan qat'i nazar, belgilanganthis
qiymatiga ega yangi funksiya yaratadi.
Call Metodi
call()
metodi funksiyani belgilangan this
qiymati va alohida-alohida taqdim etilgan argumentlar bilan chaqirish imkonini beradi.
Sintaksis:
funksiya.call(thisArg, arg1, arg2, ...)
Misol:
function salomlash(salom) {
console.log(`${salom}, ${this.ism}!`);
}
const shaxs = { ism: 'Alisher' };
salomlash.call(shaxs, 'Salom'); // Natija: Salom, Alisher!
Bu misolda call()
salomlash
funksiyasini shaxs
ni this
qiymati va 'Salom'ni argument sifatida chaqirish uchun ishlatilgan.
Apply Metodi
apply()
metodi call()
ga o'xshaydi, lekin u argumentlarni massiv (yoki massivga o'xshash obyekt) sifatida qabul qiladi.
Sintaksis:
funksiya.apply(thisArg, [argumentlarMassivi])
Misol:
function tanishtirish(salom, kasb) {
console.log(`${salom}, men ${this.ism}man va men ${kasb}man.`);
}
const shaxs = { ism: 'Bobur' };
tanishtirish.apply(shaxs, ['Salom', 'dasturchi']); // Natija: Salom, men Boburman va men dasturchiman.
Bu yerda apply()
tanishtirish
ni shaxs
ni this
qiymati va argumentlar massivi bilan chaqirish uchun ishlatilgan.
Bind Metodi
bind()
metodi qanday chaqirilishidan qat'i nazar, belgilangan this
qiymatiga ega yangi funksiya yaratadi.
Sintaksis:
const bog'langanFunksiya = funksiya.bind(thisArg, arg1, arg2, ...)
Misol:
function salomlash() {
console.log(`Salom, ${this.ism}!`);
}
const shaxs = { ism: 'Dilshod' };
const bog'langanSalomlash = salomlash.bind(shaxs);
bog'langanSalomlash(); // Natija: Salom, Dilshod!
Bu holda, bind()
this
doimiy ravishda shaxs
ga o'rnatilgan bog'langanSalomlash
nomli yangi funksiya yaratadi.
Call, Apply va Bind'ni Taqqoslash
Keling, bu metodlarni taqqoslaylik:
function yig'indi(a, b) {
return a + b + this.qiymat;
}
const obj = { qiymat: 5 };
console.log(yig'indi.call(obj, 1, 2)); // Natija: 8
console.log(yig'indi.apply(obj, [1, 2])); // Natija: 8
const bog'langanYig'indi = yig'indi.bind(obj);
console.log(bog'langanYig'indi(1, 2)); // Natija: 8
Asosiy farqlar:
call()
vaapply()
funksiyani darhol chaqiradi.bind()
uni chaqirmasdan yangi funksiya qaytaradi.call()
argumentlarni alohida-alohida qabul qiladi,apply()
esa ularni massiv sifatida qabul qiladi.
Funksiya Qarz Olish
call()
va apply()
ning kuchli foydalanish usullaridan biri - bu funksiya qarz olish, bu yerda bir obyektning metodlari boshqa obyekt tomonidan ishlatilishi mumkin.
Misol:
const shaxs1 = {
to'liqIsm: function() {
return `${this.ism} ${this.familiya}`;
}
};
const shaxs2 = {
ism: 'Jamshid',
familiya: 'Alimov'
};
console.log(shaxs1.to'liqIsm.call(shaxs2)); // Natija: Jamshid Alimov
Bu yerda shaxs2
shaxs1
dan to'liqIsm
metodini "qarz oladi".
Qisman Qo'llash
bind()
qisman qo'llash uchun ishlatilishi mumkin, bu yerda biz ba'zi oldindan belgilangan parametrlar bilan yangi funksiya yaratamiz.
Misol:
function ko'paytirish(x, y) {
return x * y;
}
const ikkilantirish = ko'paytirish.bind(null, 2);
console.log(ikkilantirish(4)); // Natija: 8
Bu holda, biz har doim o'z argumentini 2 ga ko'paytiradigan ikkilantirish
deb nomlangan yangi funksiya yaratdik.
Haqiqiy Dunyo Ssenariylardagi Foydalanish Holatlari
- Hodisa Ishlovchilari:
class MeningKomponentim {
constructor() {
this.holat = { sanoq: 0 };
this.bosilishniIshla = this.bosilishniIshla.bind(this);
}
bosilishniIshla() {
this.holatniO'zgartir({ sanoq: this.holat.sanoq + 1 });
}
}
- Metod Zanjiri:
function Zanjir() {
this.boshlash = 1;
this.qo'shuvchi = function(x) {
this.boshlash += x;
return this;
};
this.oluvchi = function() {
return this.boshlash;
};
}
const zanjir = new Zanjir();
console.log(zanjir.qo'shuvchi(1).qo'shuvchi(2).oluvchi()); // Natija: 4
- Maxsus Kontekst bilan API Chaqiruvlari:
const api = {
olish(url) {
return fetch(url).then(javob => javob.json());
},
joylash(url, ma'lumot) {
return fetch(url, {
method: 'POST',
body: JSON.stringify(ma'lumot)
}).then(javob => javob.json());
}
};
const foydalanuvchiApi = {
asosiyUrl: 'https://api.misol.com/foydalanuvchilar',
foydalanuvchiOlish(id) {
return api.olish.call(this, `${this.asosiyUrl}/${id}`);
},
foydalanuvchiYaratish(foydalanuvchiMa'lumoti) {
return api.joylash.call(this, this.asosiyUrl, foydalanuvchiMa'lumoti);
}
};
Umumiy Xatolar
this
Kontekstini Yo'qotish:
const obj = {
nom: 'MeningObyektim',
keyinroqAyt: function() {
setTimeout(function() {
console.log(this.nom);
}, 1000);
}
};
obj.keyinroqAyt(); // Natija: undefined (1 soniyadan keyin)
Tuzatish:
const obj = {
nom: 'MeningObyektim',
keyinroqAyt: function() {
setTimeout(function() {
console.log(this.nom);
}.bind(this), 1000);
}
};
obj.keyinroqAyt(); // Natija: MeningObyektim (1 soniyadan keyin)
bind
bilannew
Ishlatishni Unutish:
function Shaxs(ism) {
this.ism = ism;
}
const bog'langanShaxs = Shaxs.bind(null, 'Alisher');
const shaxs = bog'langanShaxs(); // Xato! Bunday bo'lishi kerak: const shaxs = new bog'langanShaxs();
console.log(shaxs); // undefined
console.log(window.ism); // 'Alisher' (qat'iy bo'lmagan rejimda)
Eng Yaxshi Amaliyotlar
- Funksiyani darhol ma'lum bir
this
qiymati bilan chaqirish kerak bo'lgandacall()
yokiapply()
dan foydalaning. - Keyinchalik foydalanish uchun belgilangan
this
qiymatiga ega yangi funksiya yaratmoqchi bo'lganingizdabind()
dan foydalaning. this
bog'lanish muammolaridan qochish uchun qayta chaqiruvlar uchun o'q funksiyalarini afzal ko'ring.- Qayta chaqiruv sifatida uzatiladigan metodlar uchun klass konstruktorlarida
bind()
dan foydalaning. - O'rnatilgan metodlar bilan
call()
,apply()
yokibind()
dan foydalanishda ehtiyot bo'ling, chunki bu kutilmagan xatti-harakatlarga olib kelishi mumkin.
Ishlash Samaradorligi Mulohazalari
call()
, apply()
va bind()
kuchli bo'lsa-da, ular ishlash samaradorligiga ta'sir qilishi mumkin:
bind()
odatdacall()
yokiapply()
dan sekinroq, chunki u yangi funksiya yaratadi.- Argumentlar soni ma'lum va kichik bo'lganda
apply()
call()
dan sekinroq bo'lishi mumkin. - Tsikl ichida bog'langan funksiyalar yaratish samarasiz bo'lishi mumkin. Bog'lanishni tsikldan tashqariga ko'chirishni o'ylab ko'ring.
Tsiklni optimallashtirish misoli:
// Kamroq samarali
for (let i = 0; i < 1000; i++) {
const bog'langanFn = ba'ziFunksiya.bind(null, i);
bog'langanFn();
}
// Ko'proq samarali
const bog'langanFn = ba'ziFunksiya.bind(null);
for (let i = 0; i < 1000; i++) {
bog'langanFn(i);
}
Brauzer Mosligi
call()
, apply()
va bind()
zamonaviy brauzerlarda yaxshi qo'llab-quvvatlanadi. Biroq, bind()
ECMAScript 5 da kiritilgan, shuning uchun juda eski brauzerlar uchun polyfill kerak bo'lishi mumkin:
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) {
if (typeof this !== 'function') {
throw new TypeError('Function.prototype.bind - bog'lanayotgan narsa chaqiriluvchi emas');
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function() {},
fBound = function() {
return fToBind.apply(this instanceof fNOP
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
if (this.prototype) {
fNOP.prototype = this.prototype;
}
fBound.prototype = new fNOP();
return fBound;
};
}
Tez-tez So'raladigan Savollar
- Savol:
call()
vaapply()
ni qachon ishlatishim kerak? Javob: O'tkazadigan argumentlar sonini bilganingizdacall()
dan foydalaning. Argumentlar soni dinamik bo'lganda yoki argumentlar massivini o'tkazmoqchi bo'lganingizdaapply()
dan foydalaning. - Savol: O'q(Arrow) funksiyalari bilan
call()
,apply()
yokibind()
ni ishlatishim mumkinmi? Javob: Bu metodlarni o'q funksiyalari bilan ishlatishingiz mumkin, lekin ular o'q funksiyasiningthis
bog'lanishini o'zgartirmaydi, chunki o'q funksiyalari o'z kontekstlarini leksik ravishda bog'laydi. - Savol:
bind()
prototip zanjirini qanday ta'sirlaydi? Javob:bind()
yangi funksiya yaratadi. Bog'langan funksiya asl funksiya bilan bir xil prototipga ega, lekin u asl funksiyaning prototip zanjirida emas.
Qo'shimcha Manbalar
- MDN Web Docs: Function.prototype.call()
- MDN Web Docs: Function.prototype.apply()
- MDN Web Docs: Function.prototype.bind()
- JavaScript.info: Funksiya bog'lash
- You Don't Know JS: this & Object Prototypes
- JavaScript'da this ni Aniqlik bilan Tushunish va Uni O'zlashtirish
- Call, Apply va Bind O'rtasidagi Farq