Strata kontextu v JavaScripte
Nech máme funkciu vo funkcii. Povedzme
vonkajšiu funkciu nazvime parent, a
vnútornú - child:
function parent() {
function child() {
}
}
Z predchádzajúcich lekcií viete, že ak nastavíte akúkoľvek premennú vo vonkajšej funkcii - bude dostupná vo vnútornej:
function parent() {
let str = 'abcde';
function child() {
console.log(str); // vypíše 'abcde'
}
child(); // voláme vnútornú funkciu
}
parent(); // voláme vonkajšiu funkciu
Existuje však nuansa: vnútorná funkcia má
prístup ku všetkým premenným vonkajšej, ale
nemá prístup k this. To znamená: ak
je vonkajšia funkcia naviazaná na nejaký DOM
element, potom this v nej bude ukazovať
na tento element, ale this vnútornej
funkcie - nebude!
Na čo potom bude ukazovať this
vnútornej funkcie? Odpoveď: bude rovný
undefined (v prísnom režime), pretože
funkcia nie je na nič naviazaná.
Vyskúšajme to v praxi. Nech máme daný input:
<input id="elem" value="text">
Naväzme na tento input funkciu parent,
ktorá sa bude volať pri strate fokusu inputom:
"use strict";
let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);
// Zavolá sa pri strate fokusu:
function parent() {
// tu bude nejaký kód
function child() {
// tu bude nejaký kód
}
child(); // voláme dcérsku funkciu
}
Vypíšme obsah this do
konzoly na dvoch miestach: vo funkcii parent
a vo funkcii child:
"use strict";
let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);
function parent() {
console.log(this); // vypíše odkaz na náš input
function child() {
console.log(this); // vypíše undefined
}
child();
}
Spustte tento kód, stratte fokus inputu
a pozrite sa do konzoly - uvidíte, že
prvý console.log vypíše do konzoly
odkaz na náš input, a druhý - jednoducho undefined.
Takáto situácia, kedy this neočakávaným
spôsobom neukazuje na to, čo potrebujeme, sa nazýva strata kontextu.
Nech teraz v jednej aj v druhej funkcii
budeme vypisovať value inputu. Určte,
čo sa vypíše v riadkoch kódu, označených
komentármi:
"use strict";
let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);
function parent() {
console.log(this.value); // čo vypíše?
function child() {
console.log(this.value); // čo vypíše?
}
child();
}