فرق بین bind , apply و call در جاوااسکریپت

شاید باورتون نشه ولی یکی از ابهام برانگیزترین مسائل توی جاوااسکریپت فرق بین این سه مورد هستش و حتی اوایل هم برای خودم کمی مشکل بود. شاید بگید این چه ارزشی داشت که براش مطلبی رو منتشر کنه ولی اگر بعد از خوندن این توضیحات بعدها بازم یادتون رفت فرق اینها چی بود بیاید همینجا و مجدد این مقاله کوچیک رو بخونید تا دوره و یادآوری بشه براتون :-)))

توجه: حتما برای درک بهتر مثال هارو یکبار بنویسید و اجرا کنید تا دقیق تر متوجه بشید
فرق بین bind , apply و call در جاوااسکریپت
فرق بین bind , apply و call در جاوااسکریپت

در حقیقت مورد استفاده این متدها کلا برای اجرای توابع یا همون Function هاست. متدهای apply, call و bind بصورت predefined یا به قول فارسی خودمون از پیش تعریف شده در جاوااسکریپت هستند. برای اجرا و استفاده از توابع راه های زیادی وجود داره که این هم یه مدلش هست و اتفاقا کاربرد زیادی هم داره.

مثلا کمتر کسی هست که توی React از bind برای مقدار دهی و تعیین والد متدها استفاده نکرده باشه.

استفاده از Call در جاوااسکریپت

فرض کنید یک متد یا حتی یک تابع ساده دارید که قراره اسم یا همون this.name رو چاپ کنه. به مثال زیر توجه کنید که قراره با call کار کنه :

var user = {
    name: 'Mohammad'
}
function showName() {
    console.log(this.name);
}
showName.call(user);

در مثال بالا تابع showName می خواد مقدار this.name رو در کنسول نمایش بده. ولی از اونجایکه این تابع چیزی برای this.name نداره و تعریف نشده اگر با call مقادیر آبجکت user رو بهش تزریق نکنیم در تابع های معمولی خالی و در متدهای آبجکت بصورت undefined نمایش میده. ولی اینجا با call بهش آبجکت user رو منتقل کردیم و باید مقدار Mohammad رو در کنسول نمایش بده.

نکته: در اینجا اگر با call بهش مقداری ندیم یعنی توی this اصلی که همون window هستش دنبال میگرده و چون توی window هم چیزی به اسم name نداریم باز خالی نمایش میده ! ولی اگر توی window مقداری برای name تعیین کنیم اون رو نمایش میده.

خوب حالا فرض کنید تابع showName یک ورودی یا Argument هم داره که قراره توی همون call مقدارش رو براش ارسال کنیم. کد به این شکل میشه :

var user = {
    name: 'Mohammad'
}
function showName(title) {
    console.log(this.name, title);
}
showName.call(user, 'Web Developer');

در اینجا اومدیم بعد از انتقال user و تعیین this برای تابع , مقادیر argument هاش رو (در اینجا فقط یک title دارد) هم بصورت دستی بعد از user براش Web Developer نوشتیم که بعد از چاپ Mohammad اون رو هم نمایش میده.

فقط اشتباه نکنید !!! اولی برای تعیین this بود و دومی برای ورودی های تابع , چون یک title قراره بگیره

استفاده از apply در جاوااسکریپت

کلا برای مثال اول در call اینجا apply هم شبیه به همون هستش و تفاوت ندارند. به کد زیر توجه کنید :

var user = {
    name: 'Mohammad'
}
function showName() {
    console.log(this.name);
}
showName.apply(user);

ولی برای زمانیکه قراره به argument های تابع یا متد مقداری رو ارسال کنیم شرایط فرق می کنه تفاوتشون آشکار میشه. برای apply باید مقادیر رو بصورت آرایه ارسال کنیم. به کد زیر توجه کنید :

var user = {
    name: 'Mohammad'
}
function showName(title, country) {
    console.log(this.name, title, country);
}
showName.apply(user, ['Web Developer', 'Iran']);

همانطورکه می بینید اینجا یک country هم اضافه کردم و در پایین بصورت آرایه ['Web Developer', 'Iran'] مقادیر رو به ورودی تابع ارسال کردم. یعنی دقیقا فرق بین apply و call همین بودش.

نکته: متدهای call و apply بصورت اجرا شونده هستند و تابع یا متد هدف رو اجرا می کنن. ولی اگر زمانیکه بخوایم بصورت رفرنس بسازیم و اجرا نشه مثل React باید از bind استفاده کنیم که فرق اصلی bind با این دو همین هستش و البته چیزای دیگه که در ادامه می بینیم.

استفاده از bind در جاوااسکریپت

حالا برای مثال اولمون از bind استفاده می کنیم. به کد زیر توجه کنید :

var user = {
    name: 'Mohammad'
}
function showName() {
    console.log(this.name);
}
var showName = showName.bind(user);
showName();

همانطورکه می بینید در اینجا بعد از مقداردهی به showName توسط bind اون رو داخل متغیر showName ریختیم و رفرنس تابع رو گرفت و حالا در پایین اجراش کردیم. تقریبا شبیه به همون متدهای React که برای استفاده از API هایی مثل setState می آییم (this)bind انجام میدیم و بتونیم به والد دسترسی داشته باشیم.

حالا یه مدل ورودی دار رو هم بنویسم و برای مثال دوم به argument تابع یک ورودی بدیم :

var user = {
    name: 'Mohammad'
}
function showName(title) {
    console.log(this.name, title);
}
var showName = showName.bind(user);
showName('Web Developer');

با اجرای کد بالا شبیه به قبلی ها اول اسم رو می نویسه و بعد عنوان رو در title میگیره و چاپ میشه. یعنی انگار به رفرنس this داده شده یک ورودی دادیم و title حالا برابر Web Developer شبیه یک تابع معمولی هم عمل می کنه !!!

امیدوارم مورد توجه دوستان قرار گرفته شده باشه

تا بعد خدانگهدار