назад до уроку

Виправте функцію, яка втратила 'this'

важливість: 5

Виклик askPassword() в коді наведеному нижче повинен перевіряти пароль та викликати user.loginOk/loginFail в залежності від відповіді.

Але виконання коду призводить до помилки. Чому?

Виправте виділений рядок, щоб код запрацював правильно (інші рядки не мають бути змінені).

function askPassword(ok, fail) {
  let password = prompt("Пароль?", '');
  if (password == "rockstar") ok();
  else fail();
}

let user = {
  name: 'Іван',

  loginOk() {
    alert(`${this.name} увійшов`);
  },

  loginFail() {
    alert(`${this.name} виконав невдалу спробу входу`);
  },

};

askPassword(user.loginOk, user.loginFail);

Помилка виникає тому що askPassword отримує функції loginOk/loginFail без об’єкту.

Коли вона викликає їх, їх контекст втрачено this=undefined.

Спробуємо використати bind, щоб прив’язати контекст:

function askPassword(ok, fail) {
  let password = prompt("Пароль?", '');
  if (password == "rockstar") ok();
  else fail();
}

let user = {
  name: 'Іван',

  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().