「this」を失う関数を修正する
importance: 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());
通常、これは機能し、見かけもよくなります。
ただし、askPassword
が呼び出された後、訪問者が答えて() => user.loginOk()
を呼び出す前にuser
変数が変更される可能性があるなど、より複雑な状況では信頼性が少し低くなります。