this: контекст вызова, bind, call, apply

🔍 Что такое this и почему это важно?

В JavaScript this — это контекст вызова функции. Он определяет, в каком окружении выполняется функция, и может меняться в зависимости от того, как и где её вызывают.

const user = {
  name: 'Саша',
  greet() {
    console.log(`Привет, я ${this.name}!`);
  }
};

user.greet(); // Привет, я Саша!

Здесь this ссылается на объект user, потому что метод greet вызван в его контексте. Но что, если мы извлечём метод?

const greetFunc = user.greet;
greetFunc(); // Привет, я undefined!

Ой-ой! Теперь this потерялся. Почему? Потому что функция вызвана без контекста.


🎯 Четыре правила определения this

  1. Вызов метода объектаthis = объект перед точкой
    obj.method()this = obj

  2. Обычный вызов функцииthis = undefined (в strict mode) или глобальный объект
    function() {}()this = undefined

  3. Конструктор (new)this = новый созданный объект
    new User()this = свежий экземпляр User

  4. Явное указание через call, apply, bindthis = переданный объект

function showName() {
  console.log(this.name);
}

const person1 = { name: 'Аня' };
const person2 = { name: 'Ваня' };

showName.call(person1); // Аня
showName.call(person2); // Ваня

🛠️ Инструменты управления контекстом: call, apply, bind

call и apply — срочный вызов с нужным this

Оба метода вызывают функцию с указанным контекстом, но различаются передачей аргументов:

function introduce(greeting, punctuation) {
  console.log(`${greeting}, я ${this.name}${punctuation}`);
}

const person = { name: 'Маша' };

// call — аргументы через запятую
introduce.call(person, 'Привет', '!');  // Привет, я Маша!

// apply — аргументы массивом
introduce.apply(person, ['Пока', '...']); // Пока, я Маша...

bind — постоянная привязка контекста

Создаёт новую функцию с навсегда привязанным this:

const boundIntroduce = introduce.bind(person, 'Здравствуйте');
boundIntroduce('!');  // Здравствуйте, я Маша!

💡 Стрелочные функции (() => {}) не имеют своего this! Они берут его из внешнего контекста и игнорируют call/bind.


🔥 Практика: когда что использовать?

Ситуация Инструмент Пример
Нужно вызвать функцию сейчас call / apply logger.call(context, data)
Коллбэк с фиксированным this bind button.addEventListener('click', this.handleClick.bind(this))
Метод класса в React bind в конструкторе или стрелочная функция this.handleClick = this.handleClick.bind(this);

🎮 Пример: гибкий таймер

class Timer {
  constructor(seconds) {
    this.seconds = seconds;
    this.tick = this.tick.bind(this); // Фиксируем контекст!
  }

  tick() {
    this.seconds--;
    console.log(`Осталось: ${this.seconds} сек.`);
  }

  start() {
    setInterval(this.tick, 1000);
  }
}

const timer = new Timer(5);
timer.start(); // Корректно уменьшает seconds каждую секунду

Без bind this.tick потерял бы контекст при вызове через setInterval.


🏆 Главное в трёх пунктах:

  1. this зависит от способа вызова функции.
  2. Управлять контекстом можно через call, apply, bind.
  3. Стрелочные функции не имеют this и используют внешний контекст.

Теперь ты готов укротить this в любом проекте! 🚀 Попробуй применить эти знания в своём коде уже сегодня.

Скрыть рекламу навсегда

🧠 Учёба без воды и зубрёжки

Закрытый Boosty с наработками опытного преподавателя.

Объясняю сложное так, чтобы щелкнуло.

🚀 Забрать доступ к Boosty