با یک تیر دو نشان بزنید🎯 یک هدیه ۳ میلیون تومانی به همراه ۲۵٪ تخفیف روی همه دوره‌های متخصص😍
۰ ثانیه
۰ دقیقه
۰ ساعت
۱ علی
بایند کردن به خود کلاس
جامعه جاوا اسکریپت ایجاد شده در ۱۰ تیر ۱۴۰۳

درود

 

به چه دلیل باید متد به خودش بایند بشه؟ چه در خود کلاس و چه خارج از اون.

سلام،

بایند کردن متد به خودش یعنی که این متد همیشه به همون آبجکتی که داخلش تعریف شده دسترسی داشته باشه، حتی اگه به عنوان کالبک (callback) استفاده بشه و به یه جای دیگه پاس داده بشه.

وقتی یه متد از یه کلاس به عنوان کالبک استفاده میشه، ممکنه this دیگه به اون آبجکت اصلی اشاره نکنه و به یه چیز دیگه اشاره کنه. این مشکل بیشتر توی استفاده از setTimeout، setInterval یا حتی توابعی مثل forEach که یه کالبک میگیرن، پیش میاد.

حالا فرض کن یه کلاس داریم که یه متد به اسم running داره که this.name رو لاگ میکنه:

class Runner {
  constructor(name) {
    this.name = name;
  }
  running() {
    console.log(this.name);
  }
}
const runner = new Runner('cat');
setTimeout(runner.running, 1000); // undefined یا خطا یا هیچی

توی این مثال، وقتی runner.running رو به setTimeout پاس میدی، this توی متد running دیگه به آبجکت runner اشاره نمیکنه، بلکه به window (یا undefined توی حالت strict mode) اشاره میکنه.

راه‌ حل با استفاده از بایند (bind):

میتونیم متد رو به آبجکت اصلی خودش بایند کنیم تا this همیشه به درستی کار کنه.

1. بایند کردن بیرون از کلاس:

setTimeout(runner.running.bind(runner), 1000); // cat

اینجا runner.running.bind(runner) یه تابع جدید ایجاد میکنه که this همیشه به runner اشاره میکنه.

2. بایند کردن داخل کلاس:

میتونی توی سازنده (constructor) متد رو بایند کنی:

class Runner {
  constructor(name) {
    this.name = name;
    this.running = this.running.bind(this);
  }
  running() {
    console.log(this.name);
  }
}
const runner = new Runner('cat');
setTimeout(runner.running, 1000); // cat

اینجا ما توی سازنده کلاس، this.running رو به this بایند کردیم. این کار باعث میشه که هر جا runner.running رو استفاده کنیم، this همیشه به runner اشاره کنه.

توضیحات کاملش در ویدیو آمد.

فقط یک نکته اضافه کنم، اگر به شکل زیر بنویسیم ایرادش چیه؟

setTimeout(runner.running(), 1000);

وقتی runner.running() رو توی setTimeout مینویسی، جاوااسکریپت همون لحظه runner.running رو اجرا میکنه و نتیجه اون رو (که معمولاً undefined هست) به setTimeout پاس میده. بنابراین setTimeout نمیدونه که چه تابعی رو باید بعد از یک ثانیه اجرا کنه. بنابراین در این حالت در لحظه تابع اجرا شده و بعد از ثانیه ای که دادیم چیزی اجرا نمیشود.

محسن موحد ۱۲ تیر ۱۴۰۳، ۰۰:۰۱