> В чем разница function declaration, function expression и стрелочной функции в JavaScript (JavaScript)

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

Компании: Kvando Technologies, Soft_Media_Group, РСХБ, Домклик, IT-One, Софт Медиа Групп, Сбер, TYMY, 1221 Systems, SmartWay

Стек: JavaScript

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

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

Основные различия: function declaration (FD) поднимается целиком и доступна до объявления, function expression (FE) - только после присвоения, стрелочная функция не имеет собственного this, arguments и не может быть использована как конструктор. Стрелочные функции не поднимаются и всегда анонимны. FD обязательно требует имени, FE может быть анонимным или именованным.

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

Function declaration объявляется с ключевым словом function и именем. Она полностью hoistится - и объявление, и тело функции перемещаются в начало области видимости. Поэтому её можно вызывать до строки объявления. FD создаёт собственную привязку this и имеет объект arguments.

Function expression - это присвоение функции переменной. Функция может быть анонимной или именованной. Hoisting работает только для переменной (если используется var - undefined, если let/const - Temporal Dead Zone). До строки присвоения функция недоступна. Имеет собственный this и arguments.

Стрелочная функция - синтаксический сахар для коротких функций. Ключевые отличия:

  • Не имеет собственного this - берёт его из лексического окружения (внешней функции)
  • Не имеет объекта arguments - использует rest parameters (...args)
  • Не может быть конструктором (вызов с new выбросит ошибку)
  • Не имеет свойства prototype
  • Не может быть использована как generator (нет yield)
  • Всегда анонимна (но можно присвоить переменной для отладки)

Дополнительно: стрелочные функции не поднимаются, ведут себя как FE с let/const. Их this фиксируется при создании и не может быть изменён через call, apply или bind.

На практике

Для обработчиков событий в классах React или методах объектов, где нужен доступ к this внешнего контекста, стрелочные функции - стандартный выбор. Если функция должна быть вызвана до объявления (например, для рекурсии или организации кода сверху вниз) - используйте FD. Когда нужно динамическое связывание this или доступ к arguments - FE или FD.

В современном коде стрелочные функции доминируют для колбэков, методов массивов (map, filter, reduce) и простых функций без собственного контекста. FD остаётся для объявления основных функций модуля или рекурсивных алгоритмов.

Пример кода

JAVASCRIPT
// Function declaration - доступна до объявления
console.log(sum(2, 3)); // 5
function sum(a, b) { return a + b; }
// Function expression - только после присвоения
// console.log(multiply(2, 3)); // ReferenceError
const multiply = function(a, b) { return a * b; };
console.log(multiply(2, 3)); // 6
// Стрелочная функция - нет собственного this
const obj = {
name: 'test',
regular: function() { console.log(this.name); },
arrow: () => { console.log(this.name); }
};
obj.regular(); // 'test'
obj.arrow(); // undefined (this = глобальный объект)
// Нет arguments
const logArgs = (...args) => { console.log(args); };
logArgs(1, 2, 3); // [1, 2, 3]
// Нельзя использовать как конструктор
// const instance = new (() => {}); // TypeError

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

Начните с ключевых различий: hoisting, this, arguments, возможность быть конструктором. Затем приведите примеры, когда какой тип уместен. Для senior важно показать понимание лексического окружения и области видимости. Упомяните, что стрелочные функции не имеют собственного this и не могут быть перепривязаны - это и преимущество, и ограничение. Сравните поведение в методах объектов и классах. Если спросят про производительность - скажите, что разница минимальна, но стрелочные функции создают меньше замыканий при оптимизации.

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

Глубину понимания hoisting, области видимости, контекста выполнения и механизма this. Проверяется знание тонкостей: Temporal Dead Zone для FE с let/const, различие между именованным и анонимным FE, невозможность переопределить this у стрелочной функции. Также оценивается способность выбрать правильный тип функции под задачу и объяснить trade-off.

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

  • Утверждение, что стрелочные функции не hoistятся вообще - на самом деле они подчиняются правилам переменных (TDZ для let/const)
  • Использование стрелочной функции как метода объекта, когда нужен this объекта
  • Попытка вызвать new на стрелочной функции или использовать yield
  • Путаница между именованным FE и FD - именованный FE виден только внутри самой функции (для рекурсии)
  • Забывают, что arguments в стрелочной функции ссылается на внешнюю функцию, если она есть

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

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