> Как задать 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).
Пример кода
JAVASCRIPTconst 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 - новая функция с зафиксированным thisconst 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- конструктор всегда создаёт новый объект.
> Похожие задачи по frontend
Как правильно использовать Math.random для генерации чисел от 0 до 10000 в JavaScript
В чем проблема использования колбэков в JavaScript
Как работает метод getTime у объекта Date в JavaScript
Как соединить фиксированное количество строк через разделитель в JavaScript
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью