返回課程

修復會遺失「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() 之前變更。