بازگشت به درس

تابعی که "this" را از دست می‌دهد را تصحیح کنید

اهمیت: 5

فراخوانی askPassword() در کد پایین باید رمز یا چک کند و سپس با توجه به جواب user.loginOk/loginFail را فراخوانی کند.

اما به ارور برمی‌خورد. چرا؟

خط برجسته شده را تصحیح کند تا همه چیز به درستی کار کند (بقیه خطوط نیازی به تغییر ندارند).

function askPassword(ok, fail) {
  let password = prompt("رمز؟", '');
  if (password == "rockstar") ok();
  else fail();
}

let user = {
  name: 'John',

  loginOk() {
    alert(`${this.name} وارد شد`);
  },

  loginFail() {
    alert(`${this.name} نتوانست وارد شود`);
  },

};

askPassword(user.loginOk, user.loginFail);

به دلیل اینکه ask تابع‌های loginOk/loginFail را بدون شیء دریافت می‌کند ارور ایجاد می‌شود.

زمانی که این تابع آن‌ها را فرا می‌خواند، به طور طبیعی آن‌ها this=undefined را فرض می‌کنند.

بیایید زمینه را با bind پیوند بزنیم:

function askPassword(ok, fail) {
  let password = prompt("رمز؟", '');
  if (password == "rockstar") ok();
  else fail();
}

let user = {
  name: 'John',

  loginOk() {
    alert(`${this.name} وارد شد`);
  },

  loginFail() {
    alert(`${this.name} نتوانست وارد شود`);
  },

};

askPassword(user.loginOk.bind(user), user.loginFail.bind(user));

حالا کار می‌کند.

راه‌حل جایگزین می‌تواند این باشد:

//...
askPassword(() => user.loginOk(), () => user.loginFail());

معمولا این راه‌حل هم کار می‌کند و ظاهر خوبی دارد.

اگرچه این کد در موقعیت‌های پیچیده‌تر کمتر قابل اطمینان است، زمانی که متغیر user ممکن است بعد از اینکه askPassword فراخوانی شود و قبل از اینکه کاربر جواب بدهد و () => user.loginOk() را فرا بخواند، تغییر کند.