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

Как изменить this?

1.6 Junior🔥 81 комментариев
#JavaScript Core

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

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

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

Как изменить значение this в JavaScript

Это фундаментальный вопрос о контексте выполнения. В JavaScript this — это специальная переменная, которая определяется во время выполнения кода. Давай разберемся, как его менять.

Что такое this

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

const user = {
  name: "Иван",
  greet() {
    console.log(this.name); // Иван
  }
};

user.greet(); // this === user

Но если мы передадим функцию куда-то — контекст теряется:

const greet = user.greet;
greet(); // undefined (this === window или undefined)

Способ 1: call() — явный вызов с контекстом

Это самый простой способ — передаем объект как первый аргумент:

function sayHi(greeting, punctuation) {
  console.log(greeting + " " + this.name + punctuation);
}

const user1 = { name: "Алиса" };
const user2 = { name: "Боб" };

sayHi.call(user1, "Привет", "!"); // Привет Алиса!
sayHi.call(user2, "Hello", "?"); // Hello Боб?

Синтаксис:

func.call(thisArg, arg1, arg2, ...)

Аргументы передаются списком через запятую.

Способ 2: apply() — вызов с массивом аргументов

Отличается от call() только тем, что аргументы передаются массивом:

function sum(a, b, c) {
  return this.multiplier * (a + b + c);
}

const calculator = { multiplier: 2 };

sum.call(calculator, 1, 2, 3);      // 12
sum.apply(calculator, [1, 2, 3]);   // 12 (аргументы в массиве)

Где это полезно:

const numbers = [5, 6, 2, 3, 7];
const max = Math.max.apply(null, numbers); // 7

// Или через spread operator (современнее)
const max2 = Math.max(...numbers);

Способ 3: bind() — создание новой функции с привязанным контекстом

Это создает НОВУЮ функцию с зафиксированным this. Исходная функция не меняется:

function greet(greeting) {
  console.log(greeting + ", " + this.name);
}

const user = { name: "Виктор" };

// Создаем новую функцию с привязанным контекстом
const boundGreet = greet.bind(user);
boundGreet("Привет");  // Привет, Виктор
boundGreet("Привет");  // Привет, Виктор (контекст всегда user)

Отличие от call/apply:

  • call и apply вызывают функцию сразу
  • bind возвращает новую функцию, которую можно вызвать позже
const user = { name: "Тина" };

greet.call(user, "Привет");        // Вызывается сразу
const fn = greet.bind(user, "Hi");  // Новая функция
fn();                                // Вызываем позже

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

Одна из самых частых проблем — потеря контекста в обработчиках:

class Button {
  constructor(label) {
    this.label = label;
  }
  
  onClick() {
    console.log("Нажали:", this.label);
  }
}

const btn = new Button("Отправить");

// ПРОБЛЕМА: потеря контекста
document.addEventListener("click", btn.onClick);
// this === document (или undefined)

// РЕШЕНИЕ 1: call
document.addEventListener("click", function() {
  btn.onClick.call(btn);
});

// РЕШЕНИЕ 2: bind (лучше)
const handler = btn.onClick.bind(btn);
document.addEventListener("click", handler);

// РЕШЕНИЕ 3: стрелочная функция (эффективнее)
document.addEventListener("click", () => {
  btn.onClick();
});

Способ 4: Стрелочные функции (автоматически наследуют this)

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

const user = {
  name: "Дмитрий",
  regularFunc: function() {
    console.log(this.name); // user
  },
  arrowFunc: () => {
    console.log(this.name); // undefined (берется this из внешнего скопа)
  }
};

user.regularFunc(); // Дмитрий
user.arrowFunc();   // undefined

Для методов класса стрелочная функция очень удобна:

class Counter {
  count = 0;
  
  increment = () => {
    this.count++; // this всегда === Counter
  }
}

const counter = new Counter();
const inc = counter.increment;
inc(); // Работает! this не потеряется

Сравнение методов

МетодВызовИспользование
call()СразуРедко, когда нужны разные аргументы
apply()СразуСо слабо типизированными аргументами, массивами
bind()ПозжеЧастый случай: обработчики, таймауты
СтрелкаАвтоматическиВ классах и React компонентах

React пример

// Класс-компонент
class Form extends React.Component {
  handleSubmit() {
    console.log(this.state);
  }
  
  render() {
    return (
      <button onClick={this.handleSubmit.bind(this)}>
        Отправить
      </button>
    );
  }
}

// Функциональный компонент (лучше)
function Form() {
  const handleSubmit = () => {
    console.log("Отправляем");
  };
  
  return (
    <button onClick={handleSubmit}>
      Отправить
    </button>
  );
}

Итоговые рекомендации

  1. В классах: используй bind() в конструкторе или стрелочные методы
  2. В React: функциональные компоненты с hooks (забудь о this)
  3. Для колбэков: стрелочные функции или bind()
  4. Редко: call() и apply() для низкоуровневых манипуляций

Современный JavaScript избегает явного управления this в пользу функциональных паттернов и стрелочных функций.

Как изменить this? | PrepBro