Разница между var functionName = function() {} и function functionName() {} в JavaScript
Основное различие: поднятие (hoisting)
Вы правы, ключевое отличие между этими двумя способами объявления функций — это механизм поднятия (hoisting) в JavaScript. Давайте разберёмся подробнее.
Function Declaration (объявление функции через function имя() {})
Когда вы пишете function myFunc() {}, вы используете Function Declaration. Такие функции полностью "поднимаются" (hoisted) в начало их области видимости. Это означает, что и имя функции, и её тело перемещаются вверх, поэтому вы можете вызывать функцию до её фактического объявления в коде.
// Это работает благодаря hoisting
sayHello(); // "Hello!"
function sayHello() {
console.log("Hello!");
}
// Интерпретатор видит это так:
// function sayHello() { console.log("Hello!"); }
// sayHello();
Function Expression (функциональное выражение через var/let/const)
Когда вы пишете var myFunc = function() {}, вы создаёте Function Expression. Здесь поднимается только объявление переменной (var), но не присвоенное ей значение. До момента инициализации переменная будет undefined, и попытка вызвать её как функцию приведёт к ошибке.
// Это НЕ работает
tryToCall(); // TypeError: tryToCall is not a function
var tryToCall = function() {
console.log("Вызвана!");
};
// Интерпретатор видит это так:
// var tryToCall; // поднимается, но значение undefined
// tryToCall(); // undefined() - ошибка!
// tryToCall = function() { console.log("Вызвана!"); };
Другие важные различия
- Именованные функции: Function Declaration всегда имеет имя. Function Expression может быть анонимным или именованным (для отладки):
var myFunc = function namedFunc() {} - Область видимости: Function Declaration нельзя использовать внутри блоков
if,forи т.д. в строгом режиме. Function Expression — можно. - Самовызов (IIFE): Только Function Expression можно использовать для немедленного вызова:
(function() { console.log("IIFE"); })(); - Переопределение: Function Declaration можно переопределить, просто написав новую функцию с тем же именем. С Function Expression вы перезаписываете переменную.
Что и когда использовать?
В современном JavaScript (ES6+) рекомендуется использовать const или let вместо var для Function Expression:
const myFunc = function() { ... };
// или стрелочную функцию:
const myFunc = () => { ... };
Используйте Function Declaration (function name() {}), когда:
- Функция должна быть доступна во всей области видимости
- Вы пишете рекурсивные функции (имя функции нужно для самовызова)
- Код читают другие разработчики, привыкшие к традиционному синтаксису
Используйте Function Expression (const name = function() {}), когда:
- Функция присваивается переменной условно (например, внутри if)
- Функция передаётся как аргумент (callback)
- Вы хотите избежать поднятия для лучшего контроля потока выполнения
- Вы используете стрелочные функции (они всегда являются выражениями)
Главное правило: выбирайте тот способ, который делает ваш код более читаемым и предсказуемым. Для большинства случаев в современном JavaScript Function Expression с const считается более безопасным и явным выбором.
Практические советы и подводные камни
Добавлю несколько практических моментов, которые помогут избежать ошибок.
1. Function Declaration внутри блоков
В нестрогом режиме браузеры по-разному обрабатывают Function Declaration внутри блоков. Лучше так не делать:
// Плохая практика
if (true) {
function test() { return "A"; }
} else {
function test() { return "B"; }
}
console.log(test()); // Непредсказуемый результат
2. Рекурсия и именованные Function Expression
Если вам нужна рекурсия в Function Expression, используйте именованное выражение:
const factorial = function calcFactorial(n) {
return n <= 1 ? 1 : n * calcFactorial(n - 1);
};
// calcFactorial недоступна снаружи, но работает внутри
3. Отладка в DevTools
Именованные Function Expression и Function Declaration отображаются с именем в стеке вызовов, что упрощает отладку. Анонимные функции показываются как (anonymous), что может запутать.
4. Современный стандарт
В ES6+ предпочтение отдаётся const (чтобы избежать случайного переопределения) и стрелочным функциям для коротких выражений. Однако для больших функций или методов класса традиционный синтаксис function name() остаётся актуальным.
Помните: нет "правильного" или "неправильного" способа — есть подходящий для конкретной ситуации. Главное — быть последовательным в рамках одного проекта.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги