This, контекст вызова
1. Проблема с this
Мы ожидали, что this внутри метода объекта будет ссылаться на сам объект, но оно начинает
ссылаться на кнопку, которая вызвала этот метод через обработчик события
Почему так происходит?
thisв JavaScript – это не просто ссылка на объект, которому принадлежит метод, а на контекст вызова метода.- Когда мы вызываем метод напрямую у объекта (например,
slider1.start()), this внутри этого метода действительно ссылается на сам объектslider1. - Но когда метод объекта передается в
addEventListener(например, для клика по кнопке), кнопка становится контекстом вызова. То есть, кнопка "вызывает методы от своего имени". Поэтомуthisвнутри такого метода ссылается на саму кнопку.
2. Что такое this и почему оно меняется
Чтобы решить проблему, важно глубоко понять, что такое this в JavaScript и как определяется его
значение.
this является переменной, которая автоматически создаётся и переприсваивается браузером каждый
раз, когда функция начинает работать. Браузер постоянно меняет значение this в зависимости от
того, какой объект исполняет (вызывает) метод в данный момент
Важно не то, у кого находится метод (кому он принадлежит), а в каком контексте этот метод
вызывается. Например, если кнопка вызывает метод, принадлежащий slider1, this внутри метода
будет ссылаться на кнопку, как будто у кнопки появился собственный метод.
2.1 Примеры, когда this ведет себя ожидаемо
- Когда мы вызываем
человек1.говорить(),thisвнутри говорить будет ссылаться начеловек1, потому чточеловек1является контекстом вызова. - Аналогично, при вызове
car.start()илиslider1.start(),thisвнутри метода будет ссылаться наcarилиslider1соответственно, поскольку метод вызван явно у этих объектов.
2.2 Почему this меняется в обработчиках событий
- JavaScript — интересный язык программирования, который позволяет другому объекту вызывать методы от своего имени.
- Когда мы регистрируем button.addEventListener('click',
obj.method), мы говорим кнопке: "Кнопка, когда по тебе кликнут, выполни этот метод". - В этот момент кнопка (или браузер) вызывает метод
obj.method"от своего имени". - Контекстом вызова становится кнопка, и поэтому браузер автоматически "переприсваивает"
thisвнутри методаobj.methodэтой кнопке. Метод как бы "забывает", что он принадлежал другому объекту. - Браузер постоянно перезаписывает
this: Как только функция начинает работать, браузер беретthisи присваивает ему объект, который является контекстом вызова в данный момент.
3. Замыкания (Closures) и Функции-обёртки (Wrapper Functions)
Чтобы сохранить правильный контекст this, используется техника с замыканиями и
функциями-обёртками
3.1 Сохранить ссылку на this
В начале метода start (или другого инициализирующего метода), где this корректно ссылается на
наш объект (slider1), создаётся локальная переменная (например, that) и ей присваивается
значение this. Эта переменная that "ухватилась" за наш объект slider1. В отличие от this,
that не перезаписывается браузером.
3.2. Использовать анонимную функцию-обёртку и Замыкание (Closure)
Вместо прямой передачи метода объекта в addEventListener, передаётся анонимная функция. Внутри
этой обёртки вызывается метод объекта, используя сохранённую ссылку that.
Анонимная функция "замыкает" переменную that. Это означает, что даже когда эта функция будет
вызвана кнопкой позже (при клике), она всё равно будет иметь доступ к переменной that из своей
внешней области видимости. Таким образом, метод (onShowPrevBtnClick или onShowNextBtnClick)
вызывается от имени самого объекта (slider1), что гарантирует, что this внутри
onShowPrevBtnClick или onShowNextBtnClick будет нашим объектом.


