> Как задать this явно для функции в JavaScript (JavaScript)

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

Компании: Exness

Стек: JavaScript

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

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

Явно задать this можно четырьмя способами: call, apply, bind и через new. call и apply вызывают функцию немедленно с указанным контекстом, отличаясь лишь способом передачи аргументов. bind возвращает новую функцию с навсегда привязанным this. new создаёт новый объект и делает его this внутри функции-конструктора. Также this можно задать через стрелочные функции, но они не имеют собственного this - он берётся из лексического окружения.

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

this в JavaScript определяется тем, как вызывается функция, а не где она объявлена. Для явного управления контекстом есть три основных метода на Function.prototype:

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

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

new работает иначе: он создаёт новый пустой объект, прототип которого - prototype функции, и вызывает функцию с this, указывающим на этот объект. Если функция возвращает объект явно, он будет результатом new, иначе - созданный объект.

Стрелочные функции не имеют собственного this - они наследуют его из внешней лексической области. Поэтому call, apply, bind на них не влияют, а new с ними вообще невозможен.

На практике

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

Также call часто применяется для вызова метода с явным контекстом в функциональном программировании или при работе с утилитами типа Math.max.apply(null, numbers).

Пример кода

JAVASCRIPT
const user = {
name: 'Анна',
greet(greeting, punctuation) {
return `${greeting}, ${this.name}${punctuation}`;
}
};
const otherUser = { name: 'Борис' };
// call - аргументы по отдельности
console.log(user.greet.call(otherUser, 'Привет', '!')); // "Привет, Борис!"
// apply - аргументы массивом
console.log(user.greet.apply(otherUser, ['Здравствуйте', '...'])); // "Здравствуйте, Борис..."
// bind - новая функция с зафиксированным this
const greetBoris = user.greet.bind(otherUser, 'Хай');
console.log(greetBoris('?')); // "Хай, Борис?"
// bind нельзя переопределить
const againBound = greetBoris.bind({ name: 'Виктор' });
console.log(againBound('!')); // "Хай, Борис!"
// new - this указывает на новый объект
function Person(name) {
this.name = name;
}
const p = new Person('Глеб');
console.log(p.name); // "Глеб"

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

Начни с перечисления трёх методов и их ключевого отличия: call/apply - немедленный вызов, bind - отложенный. Упомяни, что apply принимает массив аргументов, а call - список. Затем добавь new как отдельный механизм, и стрелочные функции как способ избежать проблемы с this. Подчеркни, что bind создаёт жёсткую привязку, которую нельзя переопределить. Хорошо привести пример потери контекста в обработчике событий и решение через bind или стрелочную функцию. Если спросят про производительность - bind создаёт новую функцию, что чуть дороже, но обычно некритично.

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

Интервьюер оценивает понимание динамической природы this и умение выбирать правильный инструмент под задачу. Важно показать, что ты знаешь не только синтаксис, но и поведение: невозможность переопределить bind, разницу между call и apply, особенности работы с new. Также проверяется знание edge case: что будет, если передать null или undefined как контекст (в non-strict mode заменится на глобальный объект, в strict - останется null). Глубокое понимание стрелочных функций и их отличия от обычных - тоже плюс.

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

  • Забывают, что bind возвращает новую функцию, а не вызывает исходную.
  • Пытаются переопределить this у уже привязанной функции через call или повторный bind - не работает.
  • Путают call и apply: передают массив в call или список в apply.
  • Используют стрелочную функцию с call/apply в надежде изменить this - бесполезно.
  • Не учитывают strict mode: в нём null/undefined не заменяются на глобальный объект.
  • Забывают, что new игнорирует явный this из call/apply - конструктор всегда создаёт новый объект.

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

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