Что такое this в JavaScript и как оно ведёт себя в стрелочных функциях?
MiddleJavaScript #javascript #this #arrow-functions
Вопрос
Что такое this в JavaScript и чем отличается его поведение в обычных и стрелочных функциях?
Короткий ответ
В обычной функции this определяется тем, как функция вызвана (динамически, в момент вызова). В стрелочной функции своего this нет — она берёт this лексически, из окружающей области видимости, в которой была объявлена.
Подробный ответ
Для обычных функций this зависит от способа вызова:
- Как метод объекта (
obj.method()) —thisравенobj. - Как обычная функция (
fn()) —thisравенundefinedв strict mode (илиglobalThisбез strict mode). - Через
new—thisравен новому создаваемому объекту. - Через
call/apply/bind—thisявно задаётся первым аргументом.
Стрелочные функции не имеют собственного this: они не создают новый контекст, а захватывают this из ближайшей объемлющей обычной функции на момент объявления — точно так же, как замыкание захватывает переменные. Из-за этого стрелочные функции нельзя использовать как методы объекта, если внутри нужен this самого объекта, зато они удобны для колбэков внутри методов.
Пример
const timer = {
seconds: 0,
// Обычная функция — `this` определится вызовом setInterval,
// внутри колбэка this !== timer
startBroken() {
setInterval(function () {
this.seconds++ // this — не timer, будет ошибка/NaN
}, 1000)
},
// Стрелочная функция — берёт this из startFixed(), т.е. timer
startFixed() {
setInterval(() => {
this.seconds++ // this === timer, работает корректно
}, 1000)
}
}
class Button {
label = 'OK'
// Стрелочная функция как поле класса — this всегда привязан к экземпляру,
// удобно передавать как обработчик события без .bind(this)
handleClick = () => {
console.log(this.label)
}
}
Дополнительные вопросы
- Почему
thisвнутри стрелочной функции, объявленной в глобальной области, равенundefined/globalThis? - Чем
bindотличается отcallиapply? - Как ведёт себя
thisвнутри обработчика события DOM (element.addEventListener) для обычной и стрелочной функции?