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

Как возникает контекст у функции?

2.0 Middle🔥 181 комментариев
#JavaScript Core

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

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

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

Как возникает контекст у функции?

Контекст функции (значение this) — одна из самых важных и часто непонятных концепций в JavaScript. Давайте разберёмся, как он возникает и как работает.

Что такое контекст?

Контекст — это объект, на который указывает this внутри функции. Он определяет, к каким свойствам и методам у объекта будет доступ функция.

4 способа возникновения контекста

1. Вызов как обычная функция

Когда функция вызывается просто так, this указывает на глобальный объект (в строгом режиме — undefined):

function greet() {
  console.log(this);
}

greet(); // window (в браузере) или global (в Node.js)

// В строгом режиме
"use strict";
function greet() {
  console.log(this); // undefined
}
greet();

2. Вызов как метод объекта

Когда функция вызывается как метод объекта, this указывает на сам объект:

const person = {
  name: "Иван",
  greet: function() {
    console.log(`Привет, я ${this.name}`); // this === person
  }
};

person.greet(); // Привет, я Иван

3. Явное установление контекста

Мы можем явно установить контекст через методы call(), apply() и bind():

function introduce(country, city) {
  console.log(${this.name} из ${country}, город ${city}`);
}

const person = { name: "Мария" };

// call() — сразу вызывает с контекстом
introduce.call(person, "Россия", "Москва");
// Я Мария из Россия, город Москва

// apply() — похож на call, но аргументы в массиве
introduce.apply(person, ["Россия", "Москва"]);

// bind() — создаёт новую функцию с привязанным контекстом
const boundIntroduce = introduce.bind(person, "Россия");
boundIntroduce("Санкт-Петербург");
// Я Мария из Россия, город Санкт-Петербург

4. Вызов конструктора через new

Когда функция вызывается с new, this указывает на новый объект:

function Person(name) {
  this.name = name;
  this.greet = function() {
    console.log(`Привет, я ${this.name}`);
  };
}

const person = new Person("Алексей");
person.greet(); // Привет, я Алексей

Стрелочные функции и контекст

Стрелочные функции не имеют собственного this. Они наследуют его из внешнего контекста (лексический контекст):

const person = {
  name: "Нина",
  greet: function() {
    console.log(this.name); // "Нина"
  },
  greetArrow: () => {
    console.log(this.name); // undefined (this из глобального контекста)
  },
  delayedGreet: function() {
    setTimeout(() => {
      console.log(this.name); // "Нина" (this из методе, не из setTimeout)
    }, 1000);
  }
};

person.greet();
person.greetArrow();
person.delayedGreet();

Практический пример — обработчик событий

class Button {
  constructor(id) {
    this.id = id;
    this.element = document.getElementById(id);
  }

  init() {
    // ❌ Проблема: this будет element, не Button
    this.element.addEventListener("click", this.handleClick);

    // ✅ Решение 1: arrow function
    this.element.addEventListener("click", () => this.handleClick());

    // ✅ Решение 2: bind
    this.element.addEventListener("click", this.handleClick.bind(this));
  }

  handleClick() {
    console.log(`Кнопка ${this.id} нажата`);
  }
}

Итоги

Контекст зависит от того, как вызвана функция, а не от того, где она определена. Помни об этом различии:

  • Обычный вызов → глобальный объект или undefined
  • Вызов как метод → объект, на котором вызвана
  • Явное установление → через call/apply/bind
  • Конструктор → новый объект
  • Стрелочные функции → наследуют контекст родителя