zpět k lekci

Opravte funkci, která ztrácí „this“

důležitost: 5

Volání zeptejSeNaHeslo() v následujícím kódu by mělo zkontrolovat heslo a pak podle toho, jaká je odpověď, zavolat uživatel.přihlášeníOK/přihlášeníSelhalo.

Vede však k chybě. Proč?

Opravte zvýrazněný řádek tak, aby všechno začalo fungovat správně (ostatní řádky neměňte).

function zeptejSeNaHeslo(ok, selhal) {
  let heslo = prompt("Heslo?", '');
  if (heslo == "rockstar") ok();
  else selhal();
}

let uživatel = {
  jméno: 'Jan',

  přihlášeníOK() {
    alert(`${this.jméno} přihlášen`);
  },

  přihlášeníSelhalo() {
    alert(`${this.jméno} se nedokázal přihlásit`);
  },

};

zeptejSeNaHeslo(uživatel.přihlášeníOK, uživatel.přihlášeníSelhalo);

Chyba nastane proto, že funkce zeptejSeNaHeslo obdrží funkce přihlášeníOK/přihlášeníSelhalo bez objektu.

Když je zavolá, přirozeně předpokládají this=undefined.

Navažme kontext funkcí bind:

function zeptejSeNaHeslo(ok, selhal) {
  let heslo = prompt("Heslo?", '');
  if (heslo == "rockstar") ok();
  else selhal();
}

let uživatel = {
  jméno: 'Jan',

  přihlášeníOK() {
    alert(`${this.jméno} se přihlásil`);
  },

  přihlášeníSelhalo() {
    alert(`${this.jméno} se nedokázal přihlásit`);
  },

};

zeptejSeNaHeslo(uživatel.přihlášeníOK.bind(uživatel), uživatel.přihlášeníSelhalo.bind(uživatel));

Teď to funguje.

Alternativní řešení by mohlo být:

//...
zeptejSeNaHeslo(() => uživatel.přihlášeníOK(), () => uživatel.přihlášeníSelhalo());

Obvykle to také funguje a vypadá dobře.

Je to však méně spolehlivé ve složitějších situacích, kdy se proměnná uživatel může změnit po volání zeptejSeNaHeslo, ale před odpovědí návštěvníka a voláním () => uživatel.přihlášeníOK().