修复丢失了 "this" 的函数
重要程度: 5
下面代码中对 askPassword()
的调用将会检查 password,然后基于结果调用 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
函数。
当 ask
调用这两个函数时,它们自然会认定 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
在调用 askPassword
之后但在访问者应答和调用 () => user.loginOk()
之前被修改。