← Назад к вопросам

Откуда берется контекст для стрелочной функции

2.3 Middle🔥 171 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Контекст стрелочной функции

Краткий ответ

Стрелочная функция () => {} НЕ имеет собственного контекста this. Вместо этого она наследует контекст из лексической области видимости (lexical scope) — то есть из того места в коде, где функция была определена.

Подробное объяснение

Отличие от обычной функции

const obj = {
  name: "Объект",
  // Обычная функция
  regularFunc: function() {
    console.log(this.name); // this = obj
  },
  // Стрелочная функция
  arrowFunc: () => {
    console.log(this.name); // this = window (глобальный контекст)
  }
};

obj.regularFunc(); // "Объект"
obj.arrowFunc();   // undefined (this указывает на window, а не на obj)

Как стрелочная функция берёт контекст

Когда стрелочная функция создаётся, JavaScript engine захватывает значение this из окружающей области видимости (lexical environment) в момент определения функции. Это происходит один раз при создании функции и больше никогда не меняется.

const person = {
  name: "Иван",
  greet: function() {
    // В этом месте this = person
    // Стрелочная функция наследует this = person
    const sayName = () => {
      console.log(this.name); // this = person (захвачен из greet)
    };
    sayName(); // "Иван"
  }
};

person.greet();

Использование .call() и .apply() не помогает

const obj = {
  value: 42
};

const arrowFunc = () => {
  console.log(this.value);
};

// Попытка изменить контекст через call()
arrowFunc.call(obj); // undefined, потому что this не меняется

// А обычная функция прислушивается:
const regularFunc = function() {
  console.log(this.value);
};
regularFunc.call(obj); // 42

Практические примеры

Класс с методами

class Counter {
  count = 0;

  // Стрелочная функция как поле класса
  // this всегда указывает на экземпляр Counter
  increment = () => {
    this.count++;
  };

  // Обычный метод
  // this может потеряться при передаче как callback
  decrement() {
    this.count--;
  };
}

const counter = new Counter();
const btn = document.querySelector("button");

// Стрелочная функция сохраняет this
btn.addEventListener("click", counter.increment); // Работает ✅

// Обычный метод потеряет this
btn.addEventListener("click", counter.decrement); // Проблема ❌
// Решение: (e) => counter.decrement() или bind()

Event listeners

const handler = {
  message: "Привет!",
  handle: function(event) {
    // Обычная функция — this зависит от того, как вызвана
    console.log(this.message); // undefined если this = event.target
  },
  handleWithArrow: (event) => {
    // Стрелочная — this захвачен из момента определения
    // Здесь это будет window или module object
    console.log(this.message); // Может быть проблема
  }
};

Почему это важно

  1. Предсказуемость — стрелочная функция всегда имеет одинаковый контекст
  2. Удобство в callbacks — не нужно использовать .bind()
  3. Минус в методах объектов — не подходит для методов, которые должны работать с данными объекта

Вывод

Контекст стрелочной функции определяется в момент создания функции и берётся из лексической области видимости. Это фундаментальное отличие от обычных функций, у которых контекст определяется в момент вызова и может меняться.

Откуда берется контекст для стрелочной функции | PrepBro