Загуба на контекст в JavaScript
Нека имаме функция в функция. Нека
външната функция наречем parent, а
вътрешната - child:
function parent() {
function child() {
}
}
От предишни уроци знаете, че ако зададете която и да е променлива във външната функция - тя ще бъде достъпна във вътрешната:
function parent() {
let str = 'abcde';
function child() {
console.log(str); // ще изведе 'abcde'
}
child(); // извикваме вътрешната функция
}
parent(); // извикваме външната функция
Има, обаче, нюанс: вътрешната функция има
достъп до всички променливи на външната, но не
има достъп до this. Това означава: ако
външната функция е свързана с някой DOM
елемент, то this в нея ще сочи
към този елемент, но this на вътрешната
функция - няма да го прави!
Към какво тогава ще сочи this
на вътрешната функция? Отговор: той ще е равен
на undefined (в строг режим), тъй
като функцията не е свързана с нищо.
Нека проверим на практика. Нека имаме input поле:
<input id="elem" value="text">
Нека свържем към това input поле функцията parent,
която ще се извиква при загуба на фокус от input полето:
"use strict";
let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);
// Ще се извика при загуба на фокус:
function parent() {
// тук ще има някакъв код
function child() {
// тук ще има някакъв код
}
child(); // извикваме дъщерната функция
}
Нека изведем съдържанието на this в
конзолата на две места: вътре във функцията parent
и вътре във функцията child:
"use strict";
let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);
function parent() {
console.log(this); // ще изведе препратка към нашето input поле
function child() {
console.log(this); // ще изведе undefined
}
child();
}
Стартирайте този код, загубете фокуса на input полето
и погледнете в конзолата - ще видите, че
първият console.log ще изведе в конзолата
препратка към нашето input поле, а вторият - просто undefined.
Такава ситуация, когато this по неочакван
за нас начин сочи не към това, от което
се нуждаем, се нарича загуба на контекст.
Нека сега в едната и във втората функция
да извеждаме value на input полето. Определете,
какво ще се изведе на редовете код, отбелязани
с коментари:
"use strict";
let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);
function parent() {
console.log(this.value); // какво ще изведе?
function child() {
console.log(this.value); // какво ще изведе?
}
child();
}