regresar a la lección

Arreglar una función que perdió "this"

importancia: 5

La llamada a askPassword() en el código a continuación debe verificar la contraseña y luego llamar a user.loginOk/loginFail dependiendo de la respuesta.

Pero lleva a un error. ¿Por qué?

Arregle la línea resaltada para que todo comience a funcionar correctamente (no se deben cambiar otras líneas).

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);

El error se produce porque askPassword obtiene las funciones loginOk/loginFail sin el objeto.

Cuando los llama, asumen naturalmente this = undefined.

Vamos a usar bind para enlazar el contexto:

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));

Ahora funciona.

Una solución alternativa podría ser:

//...
askPassword(() => user.loginOk(), () => user.loginFail());

Por lo general, eso también funciona y se ve bien.

Aunque es un poco menos confiable en situaciones más complejas donde la variable user podría cambiar después de que se llama a askPassword, antes de que el visitante responde y llame a () => user.loginOk ().

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().