Потеря контекста в 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 id="elem" value="text">
Привяжем к этому инпуту функцию parent,
которая будет вызываться по потери фокуса инпутом:
"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); // выведет ссылку на наш инпут
function child() {
console.log(this); // выведет undefined
}
child();
}
Запустите этот код, потеряйте фокус инпуту
и посмотрите в консоль - вы увидите, что
первый console.log выведет в консоль
ссылку на наш инпут, а второй - просто undefined.
Такая ситуация, когда this неожиданным
для нас образом указывает не на то, что нам
нужно, называется потеря контекста.
Пусть теперь в одной и во второй функции
мы будем выводить value инпута. Определите,
что выведется в строчках кода, отмеченных
комментариями:
"use strict";
let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);
function parent() {
console.log(this.value); // что выведет?
function child() {
console.log(this.value); // что выведет?
}
child();
}