Fix a function that loses "this"
The call to askPassword()
in the code below should check the password and then call user.loginOk/loginFail
depending on the answer.
But it leads to an error. Why?
Fix the highlighted line for everything to start working right (other lines are not to be changed).
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);
The error occurs because ask
gets functions loginOk/loginFail
without the object.
When it calls them, they naturally assume this=undefined
.
Let’s bind
the context:
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));
Now it works.
An alternative solution could be:
//...
askPassword(() => user.loginOk(), () => user.loginFail());
Usually that also works and looks good.
It’s a bit less reliable though in more complex situations where user
variable might change after askPassword
is called, but before the visitor answers and calls () => user.loginOk()
.