レッスンに戻る

Ask losing this

重要性: 5

下のコードの askPassword() の呼び出しは、パスワードをチェックし、その回答により user.loginOk/LoginFail を呼びます。

しかし、それはエラーになります、なぜでしょう?

すべてが正しく動作し始めるよう、ハイライトされた行を修正してください(他の行は変更しません)。

function askPassword(ok, fail) {
  let password = prompt("Password?", '');
  if (password == "rockstar") ok();
  else fail();
}

let user = {
  name: 'John',

  loginOk() {
    alert(`${this.name} logged in`);
  },

  loginFail() {
    alert(`${this.name} failed to log in`);
  },

};

askPassword(user.loginOk, user.loginFail);

ask はオブジェクトなしで関数 loginOk/loginFail を取得しているためにエラーが起きます。

それらを呼ぶとき、通常 this=undefined と想定します。

コンテキストを bind しましょう:

function askPassword(ok, fail) {
  let password = prompt("Password?", '');
  if (password == "rockstar") ok();
  else fail();
}

let user = {
  name: 'John',

  loginOk() {
    alert(`${this.name} logged in`);
  },

  loginFail() {
    alert(`${this.name} failed to log in`);
  },

};

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

これで動作します。

別の解答としては:

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

通常は動作しますが、user が要求して () => user.loginOk() を実行する間に上書きされる可能性のあるようなより複雑な状況の場合に失敗する可能性があります。