> Как вызвать функцию, чтобы this указывал на нужный объект, а не на window в JavaScript (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Домклик

Стек: JavaScript

> Пример ответа

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

Чтобы вызвать функцию с нужным значением this, используй call, apply или bind. call и apply вызывают функцию сразу, передавая контекст первым аргументом, а bind возвращает новую функцию с привязанным this. Также можно использовать стрелочные функции - они не имеют собственного this и берут его из внешнего лексического окружения. В строгом режиме ('use strict') this в обычном вызове будет undefined, а не window.

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

this в JavaScript определяется тем, как вызывается функция, а не где она объявлена. При обычном вызове fn() в нестрогом режиме this указывает на глобальный объект (window в браузере). Чтобы явно задать контекст, есть три метода:

  • fn.call(context, arg1, arg2, ...) - вызывает функцию сразу, передавая аргументы по отдельности.
  • fn.apply(context, [argsArray]) - то же самое, но аргументы передаются массивом или array-like объектом.
  • fn.bind(context, ...args) - возвращает новую функцию с навсегда привязанным this (и, опционально, частью аргументов). Вызов происходит позже.

Важно: bind не изменяет исходную функцию, а создаёт обёртку. Привязку нельзя переопределить через call или apply у уже связанной функции.

Стрелочные функции (=>) полностью игнорируют call, apply и bind - их this фиксируется на момент создания и берётся из внешней функции или модуля.

На практике

В реальном коде чаще всего bind используют для передачи метода объекта в качестве callback (например, в обработчиках событий или setTimeout). call и apply удобны для заимствования методов - например, Array.prototype.slice.call(arguments).

Также apply полезен, когда количество аргументов заранее неизвестно или они уже лежат в массиве. В современном JavaScript для этого чаще используют spread-оператор: fn(...args) - но он не меняет this.

Пример кода

JAVASCRIPT
const user = {
name: 'Анна',
greet(greeting, punctuation) {
console.log(`${greeting}, ${this.name}${punctuation}`);
}
};
const otherUser = { name: 'Пётр' };
// call - сразу, аргументы по отдельности
user.greet.call(otherUser, 'Привет', '!'); // "Привет, Пётр!"
// apply - сразу, аргументы массивом
user.greet.apply(otherUser, ['Здравствуйте', '...']); // "Здравствуйте, Пётр..."
// bind - новая функция с привязанным this
const boundGreet = user.greet.bind(otherUser, 'Хай');
boundGreet('?'); // "Хай, Пётр?"
// стрелочная функция - this из внешнего контекста
const arrowGreet = () => console.log(this); // this = window (или undefined в strict)

Как отвечать на собеседовании

Начни с прямого ответа: call, apply, bind. Затем кратко объясни разницу: call и apply - немедленный вызов, bind - создание новой функции. Упомяни стрелочные функции как альтернативу. Приведи пример из практики - например, почему setTimeout(this.method, 100) теряет контекст и как это исправить через bind. Если спросят про строгий режим - скажи, что в 'use strict' this при обычном вызове будет undefined, что защищает от случайной записи в глобальный объект.

Что проверяет интервьюер

Интервьюер оценивает:

  • понимание динамической природы this (важен способ вызова, а не объявление);
  • знание трёх методов управления контекстом и их отличий;
  • умение объяснить, почему bind не работает со стрелочными функциями;
  • способность применить знания к реальной задаче - например, потеря контекста в callback.

Типичные ошибки

  • Путать call и apply - забывать, что apply принимает массив аргументов.
  • Думать, что bind вызывает функцию сразу - на самом деле он возвращает новую функцию.
  • Пытаться переопределить this у стрелочной функции через call/apply - это не сработает.
  • Забывать, что bind создаёт новую функцию, поэтому её нельзя использовать для удаления обработчика, если не сохранить ссылку.
  • В нестрогом режиме полагаться на window как на "дефолтный" this - лучше всегда явно передавать контекст.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью