آموزش bind در جاوا اسکریپت

کامل بهرامی
1403/01/15
375
آموزش bind در جاوا اسکریپت

آموزش Bind در جاوا اسکریپت به زبانی ساده

متد bind در جاوا اسکریپت به زبانی بسیار ساده راهی برای پیوند دادن تابعی به شیئی خاص است. در این رابطه کلمه کلیدی this به تابع اجازه می‌دهد تا بر اساس شیئی که با آن مرتبط است رفتار متفاوتی داشته باشد. به طور معمول، تابع ممکن است نتایج ثابتی ایجاد کند، اما با عمل اتصال یا binding، می‌تواند رفتار خود را بسته به زمینه مد نظر تطبیق دهد. برای این منظور از متد bind استفاده می‌شود.

اگر آموزش رایگان جاوا اسکریپت را از قبل دیده باشید امکان دارد که با متد bind کم‌وبیش آشنایی داشته باشید ولی با این حال در این مطلب از مجله سبزلرن می‌خواهیم که به صورت کامل و با رویکردی کاملاً عملی به آموزش متد bind در جاوا اسکریپت بپردازیم. قبل از این که این متد را مورد بررسی دقیق قرار دهیم در ابتدا باید با مفهوم کلمه کلیدی This در جاوا اسکریپت آشنا شویم و چند مثال را در همان ابتدا بررسی کنیم تا در ادامه با دستی باز تر بتوانیم در مورد این متد سخن بگوییم.

آموزش جاوا اسکریپت

کلمه کلیدی this در جاوا اسکریپت

this در زبان برنامه نویسی جاوا اسکریپت به شیئی که به آن تعلق دارد اشاره دارد و مقدار آن بسته به نحوه فراخوانی تابع تغییر می‌کند. هنگامی‌که تابع بخشی از شی (یا متدی) است، this آن شی را نشان می‌دهد؛ اما در یک تابع معمولی، this معمولاً به شی سراسری اشاره می‌کند که معمولاً در این سناریو شی پنجره (window) در محیط‌های مرورگر است. به عنوان نمونه به این مثال توجه کنید:

let Sabz = {
    name: "ABC",
    printFunc: function () {
        console.log(this.name);
    }
}

sabz.printFunc();

در مثال بالا، this در متد printFunc به شی sabz اشاره دارد زیرا printFunc روی sabz فراخوانی می‌شود؛ بنابراین، زمانی که sabz.printFunc اجرا می‌شود، مقدار  sabz.name را چاپ می‌کند که ABC است.

همچنین در مثال زیر، ارتباط this با شی آن از بین رفته و در نتیجه خروجی تولید نمی‌شود.

let sabz = {
    name: "ABC",
    printFunc: function () {
        console.log(this.name);
    }
}

let printFunc2 = sabz.printFunc;
printFunc2();

در مثال فوق، printFunc2 به متد printFunc از شی sabz اختصاص داده می‌شود. با این حال، وقتی printFunc2 به طور مستقل، بدون اینکه به sabz گره بخورد، فراخوانی شود، اتصال this از بین می‌رود. در نتیجه، this.name به هیچ شیئی اشاره نمی‌کند و منجر به خروجی تعریف نشده می‌شود.

همچنین در مثال زیر، ما سناریوی قبلی را با استفاده از متد bind در جاوا اسکریپت بهبود می‌دهیم. متد bind یک تابع جدید ایجاد می‌کند که در آن this به شی مشخص‌شده در پرانتز آن اشاره دارد.

let sabz = {
    name: "ABC",
    printFunc: function () {
        console.log(this.name);
    }
}

let printFunc2 = sabz.printFunc.bind(sabz);
// Using bind()
// bind() takes the object sabz as a parameter
printFunc2();

در مثال فوق، printFunc2 به متد printFunc از شی sabz اختصاص داده می‌شود اما با یک زمینه خاص که با استفاده از bind در جاوا اسکریپت مشخص‌شده است. در این رابطه کلمه کلیدی this تضمین می‌کند که وقتی printFunc2 فراخوانی می‌شود، this.name به ویژگی name شی sabz اشاره می‌کند؛ بنابراین، خروجی ABC است.

در نهایت و در مثال زیر ما سه شی داریم که هر کدام ویژگی‌های متفاوتی دارند. سپس از متد bind برای مرتبط کردن یک تابع مشترک با هر شی استفاده می‌کنیم.

// Object sabz1
let sabz1= {
    name: "ABC",
    article: "C++"
}

// Object sabz2
let sabz2 = {
    name: "CDE",
    article: "JAVA"
}

// Object sabz3
let sabz3 = {
    name: "IJK",
    article: "C#"
}

// Function to print values
function printVal() {
    console.log(this.name + " contributes about " +
                this.article + "<br>");
}

// Using bind() to associate printVal with each object
let printFunc2 = printVal.bind(sabz1);
printFunc2();

let printFunc3 = printVal.bind(sabz2);
printFunc3();

let printFunc4 = printVal.bind(sabz3);
printFunc4();

هر بار که printVal را صدا می‌زنیم، با استفاده از متد bind در جاوا اسکریپت با یک شی متفاوت مرتبط می‌شود. این رویکرد به ما اجازه می‌دهد تا اطلاعات منحصربه‌فردی را در مورد هر شیء تولید کنیم. در نهایت خروجی مثال فوق خواهد بود:

ABC contributes about C++<br>
CDE contributes about JAVA<br>
IJK contributes about C#<br>

تا به اینجای مطلب پیش زمینه نسبتاً مناسبی از متد bind در Javascript ارائه کردیم و حال آماده‌ایم که به صورت جزئی‌تری به تعریف آن بپردازیم.

تابع Bind در جاوا اسکریپت چیست؟

متد bind در جاوا اسکریپت برای ایجاد نوعی تابع جدید استفاده می‌شود. هنگامی‌که این تابع جدید فراخوانی می‌شود، کلمه کلیدی this آن با مقدار خاصی که ما ارائه می‌کنیم تنظیم می‌شود. به زبان ساده، متد bind در زبان برنامه‌نویسی جاوا اسکریپت راهی برای ایجاد نوعی تابع جدید با مقداری خاص برای کلمه کلیدی this است. این متد زمانی مفید است که می‌خواهید اطمینان حاصل کنید که یک تابع همیشه با یک زمینه یا شی خاص فراخوانی می‌شود.

به عنوان مثال، اگر تابعی دارید که متعلق به یک شی است اما می‌خواهید آن را در زمینه متفاوت بدون از دست دادن ارتباطش با شی اصلی استفاده کنید، می‌توانید از bind برای ایجاد تابع جدید با زمینه مورد نظر استفاده کنید. در اینجا نحوه استفاده از متد bind در Javascript آمده است:

fn.bind(thisArg[, arg1[, arg2[, ...]]])

تشریح سینتکس فوق به صورت زیر است:

  • fn تابعی است که می‌خواهیم عمل اتصال به زمینه خاص برای آن انجام شود.
  • thisArg مقداری است که می‌خواهیم کلمه کلیدی this هنگام فراخوانی تابع محدود روی آن تنظیم شود.
  • arg1»، «arg2» و غیره، آرگومان‌های اختیاری هستند که می‌توانند هنگام فراخوانی تابع محدود به آن ارسال شوند.

برخلاف متدهای call و apply،  bind بلافاصله تابع را اجرا نمی‌کند. در عوض، نسخه جدیدی از تابع را با مقدار this با مقدار thisArg مشخص‌شده برمی‌گرداند. برای مثال کد زیر را در نظر بگیرید:

let greet = function(message) {
  console.log(message + ', ' + this.name);
};
let person = {
  name: 'John'
};

let greetJohn = greet.bind(person, 'Hello');
greetJohn(); // Output: Hello, John

در کد فوق، greet.bind(person, ‘Hello’) تابع جدید greetJohn ایجاد می‌کند که در آن this روی شی person تنظیم شده است. هنگامی‌که greetJohn فراخوانی می‌شود، Hello, John را به کنسول وارد می‌کند.

کاربرد متد bind چیست؟

متد bind در جاوا اسکریپت معمولاً در سناریوهای مختلفی استفاده می‌شود که از مهم‌ترین این کاربردها می‌توان موارد زیر را ذکر کرد:

  • کنترل‌کننده رویداد یا Event Handler

هنگام اتصال کنترل‌کننده رویداد به عناصر HTML، bind می‌تواند برای اطمینان از اجرای تابع handler با زمینه صحیح استفاده شود. در این رویکرد متد bind به ویژه هنگام کار با اشیا و متدها مفید است.

  • توابع Callback

هنگامی‌که متدهای شیء را به عنوان Callback یا توابع پاسخ به فراخوانی به سایر توابع (مانند setTimeout یا addEventListener) ارسال می‌کنید، bind به حفظ زمینه صحیح برای متد کمک می‌کند.

  • توابع جزئی

bind همچنین می‌تواند برای ایجاد توابع جزئی اعمال شده استفاده شود، جایی که برخی از آرگومان‌ها از پیش تعریف‌شده‌اند. در این رویکرد متد bind زمانی مفید است که تابعی با چندین پارامتر دارید، اما می‌خواهید برخی از آن‌ها را اصلاح کرده و تابعی جدید با پارامترهای کمتر ایجاد کنید.

  • توابع Currying

مشابه توابع جزئی، bind را می‌توان برای توابع currying نیز استفاده کرد که در آن شما زنجیره‌ای از توابع را ایجاد می‌کنید که هر کدام یک آرگومان را با اعمال مکرر bind می‌گیرند.

  • ایجاد نام مستعار

bind را می‌توان برای ایجاد توابع مستعار برای متدهای موجود استفاده کرد.

bind در جاوا اسکریپت در اصل متدی همه‌کاره است که به مدیریت و کنترل زمینه‌ای که توابع در آن اجرا می‌شوند کمک می‌کند و از رفتار قابل پیش‌بینی و کد تمیزتر در سناریوهای مختلف اطمینان می‌دهد.

استفاده از bind در جاوا اسکریپت برای اتصال تابع

وقتی متدی از یک شی را به عنوان نوعی فراخوانی به تابع دیگری ارسال می‌کنید، گاهی اوقات کلمه کلیدی this گم می‌شود. فرض کنید یک شی به نام person با متدی به نام getName داریم. اگر بخواهیم از person.getName به عنوان نوعی تابع تماس برای setTimeout استفاده کنیم، ممکن است آن‌طور که انتظار می‌رود کار نکند. طبق مثال زیر:

let person = {
    name: 'John Doe',
    getName: function() {
        console.log(this.name);
    }
};

setTimeout(person.getName, 1000);

خروجی مثال بالا ممکن است تعریف نشده (undefined) را به جای John Doe بیرون دهد. این اتفاق می‌افتد زیرا setTimeout، person.getName را جداگانه از شی person دریافت می‌کند، بنابراین نمی‌داند this باید به چه چیزی اشاره کند.

برای حل این مشکل، می‌توانیم تماس person.getName را در تابعی ناشناس قرار دهیم یا از متد bind استفاده کنیم. طبق مثال زیر:

// Using an anonymous function
setTimeout(function () {
    person.getName();
}, 1000);

// Using the bind() method
let f = person.getName.bind(person);
setTimeout(f, 1000);

در مثال فوق با bind در جاوا اسکریپت تابع جدیدی ایجاد می‌کنیم که در آن this به طور دائم روی شی person تنظیم می‌شود. سپس، این تابع جدید f را به setTimeout منتقل کرده و مطمئن می‌شویم که this زمینه صحیح خود را هنگام فراخوانی person.getName حفظ می‌کند.

استفاده از bind برای قرض گرفتن متدها از یک شی متفاوت

فرض کنید دو شی runner با متد run و flyer با متد fly دارید. اگر بخواهید شی flyer نیز بتواند اجرا شود، می‌توانید از متد bind به صورت زیر استفاده کنید.

let runner = {
    name: 'Runner',
    run: function(speed) {
        console.log(this.name + ' runs at ' + speed + ' mph.');
    }
};

let flyer = {
    name: 'Flyer',
    fly: function(speed) {
        console.log(this.name + ' flies at ' + speed + ' mph.');
    }
};

برای اینکه flyer بتواند اجرا شود، می‌توانید تابعی جدید با استفاده از bind به صورت زیر ایجاد کنید:

let run = runner.run.bind(flyer, 20);
run();

در کد فوق ما از متد bind در runner.run استفاده می‌کنیم و flyer را به عنوان اولین آرگومان و 20 را به عنوان آرگومان دوم پاس می‌کنیم. سپس تابع run را فراخوانی خواهیم کرد. خروجی به صورت زیر خواهد بود:

Flyer runs at 20 mph.

استفاده از bind در جاوا اسکریپت به شی اجازه می‌دهد تا یک متد را از یک شی دیگر بدون کپی کردن آن قرض بگیرد. این ویژگی در جاوا اسکریپت قرض تابع نامیده می‌شود.

مزایا و معایب استفاده از متد bind در جاوا اسکریپت چیست؟

استفاده از متد bind در Javascript چندین مزیت دارد اما برخی از اشکالات بالقوه را نیز دارد که باید در نظر گرفت:

مزایای این متد به صورت زیر است:

  • قابلیت اتصال آسان

این متد به شما این امکان را می‌دهد که صریحاً کلمه کلیدی this را به یک شی خاص متصل کنید. این متد تضمین می‌کند که تابع همیشه در زمینه مورد نظر اجرا می‌شود که می‌تواند از رفتارهای غیرمنتظره و اشکالات جلوگیری کند.

  • قابلیت استفاده مجدد تابع

با ایجاد توابع محدود با bind، می‌توانید از توابع در زمینه‌های مختلف بدون تغییر تعاریف اصلی آن‌ها استفاده مجدد کنید. این امر قابلیت استفاده مجدد و نگهداری کد را ارتقا می‌دهد.

  • توابع جزئی

bind می‌تواند برای ایجاد توابع جزئی اعمال شده استفاده شود، جایی که برخی از آرگومان‌ها از پیش تعریف‌شده‌اند.

  • اجتناب از درگیر کردن دامنه جهانی

هنگام ارسال متدهای شی به عنوان بازخوانی، bind با اطمینان از اینکه تابع در زمینه شی مورد نظر اجرا می‌شود، از درگیر شدن بیش از حد دامنه جهانی جلوگیری می‌کند.

معایب این متد به صورت زیر است:

  • سربار عملکرد

ایجاد توابع محدود با bind مستلزم مقداری سربار عملکرد است که این می‌تواند بر عملکرد برنامه شما تأثیر بگذارد و این عیب به خصوص در سناریوهایی که برنامه به عملکردی حیاتی نیاز دارد به خوبی خودش را نشان می‌دهد.

  • مصرف حافظه

از آنجایی که bind اشیاء تابع جدیدی تولید می‌کند، استفاده بیش از حد از آن می‌تواند منجر به افزایش مصرف حافظه شود.

  • سردرگمی

استفاده بیش از حد از bind در جاوا اسکریپت می‌تواند منجر به کدهایی شود که درک و نگهداری آن دشوار است، به خصوص برای توسعه‌دهندگانی که با رفتار آن آشنا نیستند.

  • پتانسیل نشت حافظه

هنگام استفاده از bind در سناریوهای خاص، مانند شنوندگان رویداد، احتمال نشت حافظه در سناریوهایی نادر وجود دارد. شنونده‌های رویداد بدون محدودیت می‌توانند از جمع‌آوری اشیاء در زباله‌ها جلوگیری کنند که به مرور زمان منجر به نشت حافظه می‌شود.

در حالی که bind ابزاری قدرتمند برای مدیریت بافت تابع و ارتقای قابلیت استفاده مجدد کد است، مهم است که مزایای آن را در برابر معایب احتمالی آن سنجیده و از آن در برنامه‌های جاوا اسکریپت خود به طور منطقی استفاده کنید.

آموزش جاوا اسکریپت

در چه سناریوهایی نباید از متد bind استفاده کنیم؟

چندین سناریو وجود دارد که استفاده از متد bind در جاوا اسکریپت ممکن است بهترین رویکرد نباشد. این سناریوها به صورت موارد زیر هستند:

  • برنامه‌های کاربردی حیاتی

در برنامه‌هایی که عملکرد آن‌ها بسیار مهم است، استفاده بیش از حد از bind می‌تواند سربار غیرضروری را به دلیل ایجاد اشیاء تابع جدید ایجاد کند. در چنین سناریوهایی، توصیه می‌شود که استفاده از bind(را به حداقل برسانید و روش‌های جایگزین را برای مدیریت بافت تابع انتخاب کنید.

  • فراخوانی‌های توابع عمیق تودرتو

استفاده از bind در فراخوانی‌های تابع عمیق تودرتو می‌تواند درک و نگهداری کد را سخت‌تر کند.

  • متدهای نمونه اولیه در جاوا اسکریپت

هنگام تعریف متدها بر روی نمونه‌های اولیه شی، استفاده از bind برای اتصال می‌تواند منجر به رفتار غیرمنتظره شود، زیرا تابع محدود هیچ تغییری را در زنجیره نمونه اولیه به ارث نمی‌برد.

  • اتصال با زمینه پویا

اگر زمینه‌ای که یک تابع در آن اجرا می‌شود نیاز به تغییر پویا بر اساس شرایط زمان اجرا داشته باشد، استفاده از bind ممکن است مناسب نباشد. در چنین مواردی، بهتر است به صورت دستی زمینه تابع را با استفاده از call یا Apply در جاوا اسکریپت مدیریت کنید، یا کد را تغییر دهید تا از نیاز به اتصال متن پویا به طور کامل اجتناب شود.

متدهای و رویکردهای جایگزین برای متد bind در جاوا اسکریپت

در جاوا اسکریپت، چندین متد و تکنیک جایگزین برای متد bind وجود دارد که می‌تواند به جای آن برای مدیریت بافت تابع و دستیابی به عملکرد مشابه استفاده شود که در زیر این روش‌های جایگزین همراه با مثال آورده شده‌اند.

توابع پیکان

توابع پیکان (`=>`) به صورت لغوی کلمه کلیدی this را به زمینه مدنظر متصل می‌کنند، به این معنی که آن‌ها مقدار this را از کد در زمان تعریف خود به ارث می‌برند. این امر نیاز به اتصال صریح با استفاده از bind را از بین می‌برد. با این حال، توابع پیکان را نمی‌توان به عنوان سازنده استفاده کرد و زمینه this خود را ندارند.

let obj = {
    name: 'John',
    sayName: () => {
        console.log(this.name); // 'this' refers to the outer scope
    }
};

متدهای call و apply

به جای استفاده از bind در جاوا اسکریپت، می‌توانید از متدهای call یا apply برای تعیین صریح زمینه this هنگام فراخوانی تابع استفاده کنید. این متدها بلافاصله تابع را با مقدار this مشخص‌شده و آرگومان‌های اختیاری فراخوانی می‌کنند.

let obj1 = { name: 'John' };
let obj2 = { name: 'Jane' };

function sayName() {
    console.log(this.name);
}

sayName.call(obj1); // 'John'
sayName.apply(obj2); // 'Jane'

توابع Closure

می‌توانید با تعریف تابع wrapper که تابع اصلی و زمینه مورد نظر آن را در برمی‌گیرد، یک بسته یا Closure ایجاد کنید. این کار به شما امکان می‌دهد تا زمانی که تابع فراخوانی می‌شود، زمینه صحیح this را حفظ کنید.

let obj = { name: 'John' };

function sayNameClosure() {
    let self = this;
    return function() {
        console.log(self.name);
    };
}

let boundFunc = sayNameClosure.call(obj);
boundFunc(); // 'John'

پارامترهای destructuring و rest در ES6

ES6 پارامترهای destructuring و rest را معرفی می‌کند که می‌تواند برای ضبط و ارسال آرگومان‌ها به تابع استفاده شود. این رویکرد می‌تواند برای ایجاد توابع مرتبه بالاتر که زمینه را حفظ می‌کنند مفید باشد.

let obj = { name: 'John' };

function sayNameWithArgs(...args) {
    console.log(args[0].name);
}

let boundFunc = sayNameWithArgs.bind(null, obj);
boundFunc(); // 'John'

Polyfill

اگر نیاز به پشتیبانی از مرورگرهای قدیمی دارید که به طور بومی از bind پشتیبانی نمی‌کنند، می‌توانید یک polyfill برای متد bind با استفاده از متدهای call یا apply به صورت زیر ایجاد کنید.

if (!Function.prototype.bind) {
    Function.prototype.bind = function(thisArg) {
        var fn = this,
            args = Array.prototype.slice.call(arguments, 1);
        return function() {
            return fn.apply(thisArg, args.concat(Array.prototype.slice.call(arguments)));
        };
    };
}

این متدها و روش‌های جایگزین انعطاف‌پذیری را فراهم می‌کنند و به شما این امکان را می‌دهند که بافت و زمینه اجرایی تابع را به طور مؤثر بدون تکیه‌بر متد bind در جاوا اسکریپت مدیریت کنید. در این رابطه بهتر است روشی را انتخاب کرده که به بهترین وجه با الزامات و محدودیت‌های پروژه شما مطابقت دارد.

آموزش جاوا اسکریپت از صفر تا صد

متد bind در جاوا اسکریپت ابزاری قدرتمند برای مدیریت زمینه اجرایی تابع است که به توسعه‌دهندگان این امکان را می‌دهد تا به صراحت مقدار کلمه کلیدی this را در تابعی تنظیم کنند. این متد در اصل امکان ایجاد توابع جدید با زمینه‌های از پیش تعریف‌شده را فراهم می‌کند، رفتار قابل پیش‌بینی را تضمین کرده و قابلیت استفاده مجدد کد را ارتقا می‌دهد. در مطلب فوق از مجله سبز لرن ما اطلاعات کاملی از متد bind در جاوا اسکریپت ارائه کردیم. به امید اینکه برای شما مفید بوده باشد.

قضیه متد bind در JAvascript فقط و فقط یکی از مباحث مهم و حیاتی جاوا اسکریپت است. برای آن دسته از افرادی که می‌خواهند که به همه مسائل و چالش‌های جاوا اسکریپت مسلط شوند، مطالعه و آموزش دیدن اهمیت بسیار زیادی دارد. در این رابطه توصیه ما به شما شرکت در دوره آموزش صفر تا صد جاوا اسکریپت سبز لرن است. در این دوره آموزشی شما از صفر تا صد جاوا اسکریپت را با رویکردی متفاوت و کاربردی یاد می‌گیرد و در عین حال پشتیبانی اساتید دوره را دریافت خواهید کرد.

آموزش جاوا اسکریپت

نظرات
ثبت نظر جدید
امیر حسین | کاربر
1403/01/22

بسیار عالی

آموزش جاوا اسکریپت