Что такое this и как оно работает в стрелочной функции?

this в JavaScript — это ключевое слово, которое указывает на контекст выполнения функции. Значение this зависит от того, как вызывается функция, а не от того, где она объявлена.

1. Поведение this в обычных функциях

В обычной функции (function) значение this определяется в момент вызова:

  • В глобальном контексте (в браузере) this ссылается на window.

  • В методах объекта — на сам объект.

  • В функциях-обработчиках событий — на элемент, на котором висит обработчик.

  • В конструкторах (new) — на создаваемый экземпляр.

  • В строгом режиме ('use strict') в глобальной функции this будет undefined.

Примеры:

function show() {
console.log(this);
}
show(); // в браузере: window (в обычном режиме)
const obj = {
name: 'Alice',
greet() {
console.log(this.name);
}
};
obj.greet(); // Alice
const person = {
name: 'Bob',
sayHi: function () {
setTimeout(function () {
console.log(this.name); // undefined или window.name
}, 1000);
}
};
person.sayHi();

2. Особенности this в стрелочной функции

Стрелочные функции (=>) не имеют своего собственного this. Вместо этого они наследуют this из окружающего лексического контекста, в котором были созданы.

Это значит:

  • this в стрелочной функции не зависит от способа вызова;

  • this не меняется при использовании методов .call(), .apply(), .bind();

  • стрелочные функции нельзя использовать как конструкторы (будет ошибка).

Пример:

const obj = {
name: 'Alice',
greet: function () {
const arrow = () => {
console.log(this.name);
};
arrow();
}
};
obj.greet(); // Alice

В этом примере arrow — стрелочная функция. Она определена внутри метода greet, а this в arrow берётся из greet, то есть this указывает на obj.

3. Отличие от обычной функции внутри метода

const obj = {
name: 'Bob',
greet: function () {
setTimeout(function () {
console.log(this.name);
}, 1000);
}
};
obj.greet(); // undefined

Здесь внутри setTimeout обычная функция. this в ней — это глобальный объект (или undefined в strict mode).

Решение с помощью стрелочной функции:

const obj = {
name: 'Bob',
greet: function () {
setTimeout(() => {
console.log(this.name);
}, 1000);
}
};
obj.greet(); // Bob

4. Стрелочные функции и методы объектов

Если стрелочную функцию назначить как метод объекта, this не будет указывать на сам объект:

const obj = {
name: 'John',
greet: () => {
console.log(this.name);
}
};
obj.greet(); // undefined

this в стрелочной функции здесь ссылается не на obj, а на внешний контекст (например, window), потому что стрелка не создаёт свой this.

5. Влияние call/apply/bind на стрелочные функции

Стрелочную функцию нельзя привязать к другому this:

const arrow = () => {
console.log(this);
};
const obj = { a: 1 };
arrow.call(obj); // всё равно  внешний \`this\`
arrow.apply(obj); // то же самое
arrow.bind(obj)(); // не сработает

6. Внутри классов

В классах стрелочные функции полезны для сохранения контекста this, особенно в колбэках:

class Counter {
constructor() {
this.count = 0;
}
start() {
setInterval(() => {
this.count++;
console.log(this.count);
}, 1000);
}
}
const c = new Counter();
c.start();

Стрелочная функция внутри setInterval берёт this из метода start, то есть указывает на экземпляр класса.

7. Использование в обработчиках событий

Если обработчик определён через стрелочную функцию, this внутри будет не элемент, а внешний контекст:

const button = document.querySelector('button');
button.addEventListener('click', () => {
console.log(this); // НЕ <button>, а внешний \`this\`
});

Если нужно, чтобы this указывал на элемент — использовать обычную функцию:

button.addEventListener('click', function () {
console.log(this); // <button>
});

8. Стрелочные функции и конструкция new

Стрелочную функцию нельзя использовать как конструктор:

const A = () => {};
const obj = new A(); // TypeError: A is not a constructor

Потому что у стрелочной функции отсутствует свойство [[Construct]] и this.

9. Поведение в стрелке внутри стрелки

const outer = () => {
return () => {
console.log(this);
};
};
const fn = outer();
fn(); // \`this\` берется из внешней стрелки  она тоже не имеет \`this\`

Обе стрелки не создают this. В результате this будет из контекста, где была объявлена outer.

10. Поведение в строгом режиме

Стрелочные функции всегда работают так, как будто находятся в строгом режиме. Но this в них не определяется — берётся из внешнего лексического окружения:

'use strict';
const obj = {
val: 1,
arrow: () => {
console.log(this); // window или undefined в node
}
};
obj.arrow(); // window в браузере

11. В замыканиях

Стрелочная функция часто используется вместе с замыканиями для сохранения контекста:

function Timer() {
this.seconds = 0;
setInterval(() => {
this.seconds++;
console.log(this.seconds);
}, 1000);
}
new Timer();

Без стрелки this внутри setInterval не указывал бы на экземпляр Timer.

12. Поведение в классе и bind

Стрелка — альтернатива bind в методах классов:

class User {
constructor(name) {
this.name = name;
}
sayHi = () => {
console.log(this.name);
};
}
const user = new User('Elena');
const f = user.sayHi;
f(); // Elena

Если бы sayHi был обычным методом, при передаче f = user.sayHi this бы терялся. Стрелка сохраняет this автоматически.