Функции в JavaScript: объявление, выражение, стрелки
Содержание
О проверке кода. Примеры не запускались — в отличие от материалов по Node.js с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».
Функции — сердце JavaScript. Способов объявить их несколько, и разница между ними — не стиль, а поведение. Разберём.
Три способа объявить функцию
// 1. объявление (function declaration)
function add(a, b) {
return a + b;
}
// 2. выражение (function expression)
const add = function (a, b) {
return a + b;
};
// 3. стрелочная функция (arrow)
const add = (a, b) => a + b;
Все три складывают два числа, но ведут себя по-разному в трёх вещах: всплытии, this и краткости.
Объявление против выражения: всплытие
// ✅ работает — объявление ВСПЛЫВАЕТ
console.log(sum(2, 3)); // 5
function sum(a, b) { return a + b; }
// ❌ ошибка — выражение НЕ всплывает
console.log(mul(2, 3)); // ReferenceError
const mul = (a, b) => a * b;
Объявление функции всплывает целиком (hoisting) — её можно вызвать в коде выше, чем она написана. Выражение не всплывает: до строки объявления переменная в «мёртвой зоне», как обычная const.
Практически это значит: объявления дают свободу расположения (вспомогательные функции внизу файла), выражения требуют объявить до использования. Оба подхода рабочие; современный код чаще использует стрелочные выражения.
Стрелки: краткость и отсутствие своего this
Стрелочные функции — не просто короткая запись. У них два принципиальных отличия.
Краткость нарастает по мере упрощения:
(a, b) => { return a + b; } // полная форма
(a, b) => a + b // неявный return — без {} и return
x => x * 2 // один параметр — без скобок
() => 42 // без параметров
() => ({ x: 1 }) // вернуть объект — в скобках!
Последняя строка — частая ловушка: () => { x: 1 } вернёт undefined (фигурные скобки поймут как тело), поэтому объект оборачивают в круглые: () => ({ x: 1 }).
Отсутствие своего this — главное. Стрелка берёт this из окружения и не меняет его при вызове:
const timer = {
seconds: 0,
start() {
setInterval(() => this.seconds++, 1000); // this — это timer ✅
},
};
Стрелочная
Для колбэков
- Нет своего
this— берёт из окружения - Короткая запись, неявный return
- Нет
arguments - Нельзя вызвать через
new - Идеальна как колбэк
Обычная (function)
Для методов и конструкторов
- Свой
thisпо правилам вызова - Есть
arguments - Можно
new - Всплывает (если declaration)
- Метод объекта — только она
Правило: стрелка для колбэков, обычная для методов. Стрелка как метод объекта не сработает — this будет не объектом.
Параметры по умолчанию
// современно
function greet(name = 'гость', greeting = 'Привет') {
return `${greeting}, ${name}!`;
}
greet(); // "Привет, гость!"
greet('Аня'); // "Привет, Аня!"
Значение по умолчанию подставляется, только если аргумент не передан (undefined). Это заменило старый приём:
// ❌ старый способ — ломается на falsy
function old(count) {
count = count || 10; // при count === 0 подставит 10!
}
count || 10 подставляет 10 при любом ложном значении — включая 0 и пустую строку, которые могут быть валидными. Параметры по умолчанию срабатывают строго на undefined, поэтому 0 проходит корректно.
rest и spread: работа с множеством аргументов
// rest — собрать аргументы в массив
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4); // 10 — numbers это [1, 2, 3, 4]
// spread — разложить массив в аргументы
const nums = [1, 2, 3];
Math.max(...nums); // 3
...args в параметрах (rest) собирает все аргументы в настоящий массив — с map, filter, reduce. Это заменило старый псевдомассив arguments, у которого методов массива не было и который работал только в обычных функциях. Про spread и rest подробнее.
Функция — это объект
Последнее и, возможно, самое важное для понимания языка. Функции в JavaScript — значения первого класса: с ними можно всё то же, что с числом или строкой.
const fn = () => 42; // присвоить переменной
[fn, fn].forEach(f => f()); // положить в массив
setTimeout(fn, 1000); // передать в другую функцию
function makeAdder(x) {
return (y) => x + y; // вернуть функцию из функции
}
Именно потому, что функцию можно передать в другую функцию, работают колбэки, map/filter/forEach, обработчики событий и вся асинхронность. А потому, что её можно вернуть и она помнит окружение, работают замыкания. Это фундамент, на котором стоит функциональный стиль JavaScript.
Смежные темы: this и контекст — почему стрелка для колбэков; замыкания — функции, помнящие окружение; область видимости — про всплытие. Полный список — в уроках JavaScript.