返回课程

修复一个丢失“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 变量可能在 askPassword 被调用后,但在访客回答并调用 () => user.loginOk() 之前发生改变。