> Можно ли передать функцию как аргумент в другую функцию в JavaScript (JavaScript)

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

Компании: EdenAI

Стек: JavaScript

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

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

Да, в JavaScript функции - это объекты первого класса, поэтому их можно передавать как аргументы в другие функции. Это основа функционального программирования и таких паттернов, как callbacks, higher-order functions и middleware. Передача функции позволяет инкапсулировать поведение и делегировать его выполнение, что делает код более гибким и переиспользуемым.

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

В JavaScript функции являются объектами первого класса (first-class citizens). Это означает, что они могут быть:

  • присвоены переменным
  • переданы как аргументы
  • возвращены из других функций
  • сохранены в структурах данных

Когда функция передаётся как аргумент, она называется callback-функцией. Принимающая функция называется higher-order function. Важно понимать, что передаётся сама ссылка на функцию, а не результат её вызова. Поэтому при передаче пишут fn, а не fn().

Механика работы: вызывающая сторона определяет функцию (или использует стрелочную), передаёт её в другую функцию, которая в нужный момент вызывает её, возможно с аргументами. Это позволяет абстрагировать алгоритм от конкретной реализации шага.

В современном JavaScript это повсеместно используется: Array.prototype.map, filter, reduce, обработчики событий, setTimeout, промисы, middleware в Express, композиция функций и т.д.

На практике

На практике передача функций как аргументов решает несколько задач:

  • Асинхронность: колбэки для обработки результатов после завершения операций (сетевые запросы, таймеры).
  • Абстракция: одна функция управляет потоком, а конкретное поведение делегируется переданной функции.
  • Композиция: построение сложных операций из простых функций.
  • Инверсия управления: библиотеки вызывают предоставленные пользователем функции в нужный момент.

Важно различать передачу функции и передачу результата её вызова. Частая ошибка - написать fn() вместо fn при передаче, что приводит к немедленному выполнению и передаче результата.

Также стоит помнить про контекст (this). Обычные функции имеют собственный this, стрелочные - наследуют от внешней области. При передаче методов объекта как колбэков нужно использовать bind, стрелочные функции или замыкания.

Пример кода

JAVASCRIPT
// Простая передача функции
function applyOperation(a, b, operation) {
return operation(a, b);
}
const add = (x, y) => x + y;
const multiply = (x, y) => x * y;
console.log(applyOperation(5, 3, add)); // 8
console.log(applyOperation(5, 3, multiply)); // 15
// Асинхронный колбэк
function fetchData(url, onSuccess, onError) {
setTimeout(() => {
if (url) {
onSuccess({ data: 'response' });
} else {
onError(new Error('no url'));
}
}, 100);
}
fetchData(
'/api',
(response) => console.log('Успех:', response),
(error) => console.error('Ошибка:', error)
);
// Передача метода объекта с сохранением контекста
const user = {
name: 'Анна',
greet() {
console.log(`Привет, я ${this.name}`);
}
};
setTimeout(user.greet, 100); // this потерян, будет undefined
setTimeout(user.greet.bind(user), 100); // работает
setTimeout(() => user.greet(), 100); // тоже работает
// Использование встроенных higher-order функций
const numbers = [1, 2, 3, 4];
const doubled = numbers.map(n => n * 2);
const evens = numbers.filter(n => n % 2 === 0);
const sum = numbers.reduce((acc, n) => acc + n, 0);

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

Начните с прямого ответа "да", затем объясните концепцию first-class citizens. Приведите пример из практики - лучше всего map или обработчик события. Покажите разницу между передачей функции и её вызова. Упомяните про контекст и способы его сохранения. Если спросят про производительность - отметьте, что создание функций на лету может создавать лишние аллокации, но в современных движках это оптимизируется.

Хорошо добавить пример из реальной библиотеки: middleware в Express, колбэки в промисах, функции-редьюсеры в Redux. Это покажет понимание не только синтаксиса, но и архитектурных паттернов.

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

Интервьюер проверяет:

  • понимание фундаментальной концепции функций как объектов
  • умение отличать передачу ссылки от вызова
  • знание практических применений: callbacks, higher-order functions
  • понимание проблем с контекстом и способов их решения
  • способность объяснить, зачем это нужно в реальных проектах
  • знание встроенных методов, использующих этот механизм

Для senior-позиции важно показать, что вы понимаете не только "как", но и "зачем", и можете применить это в архитектуре приложения.

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

  • Передача fn() вместо fn - функция выполняется сразу, передаётся результат.
  • Потеря контекста при передаче методов объекта без bind или стрелочной функции.
  • Создание избыточных анонимных функций в циклах, что приводит к проблемам с замыканиями.
  • Непонимание, что колбэк может вызываться несколько раз или не вызываться вовсе - нужна проверка.
  • Забывание обработать ошибки внутри переданной функции.
  • Передача функции, которая ожидает аргументы, без их предоставления в месте вызова.
  • Использование стрелочных функций там, где нужен собственный this (например, в методах объекта).

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

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