Function Declaration

Объявление функции (Function Declaration) — классический способ создания именованной функции, которая поднимается (hoisting) целиком и доступна в любом месте своей области видимости.

Зачем нужно

Function Declaration — самый простой и читаемый способ объявить функцию. Благодаря hoisting такие функции можно вызывать до места их объявления в коде, что позволяет организовать код по принципу «сначала вызовы, потом реализация».

Где используется

Основной способ объявления функций в большинстве JavaScript-программ. Подходит для утилит, хелперов, обработчиков событий, модульных функций.

Предпосылки

Введение в JavaScript, Переменные

Синтаксис

function имяФункции(параметр1, параметр2) {
  // тело функции
  return результат;
}

Базовый пример

function greet(name) {
  return `Привет, ${name}!`;
}

console.log(greet('Алиса')); // "Привет, Алиса!"

Функция без return

function logMessage(message) {
  console.log(`[LOG]: ${message}`);
  // return undefined — неявно
}

const result = logMessage('тест');
console.log(result); // undefined

Hoisting (всплытие)

Function Declaration поднимается целиком — и имя, и тело:

// Можно вызвать ДО объявления
sayHello; // "Привет!"

function sayHello() {
  console.log('Привет!');
}

Это отличает Function Declaration от Function Expression:

// sayBye; // TypeError: sayBye is not a function
const sayBye = function {
  console.log('Пока!');
};

Параметры и аргументы

Параметры по умолчанию

function createUser(name, role = 'user', active = true) {
  return { name, role, active };
}

console.log(createUser('Иван'));
// { name: 'Иван', role: 'user', active: true }

console.log(createUser('Админ', 'admin'));
// { name: 'Админ', role: 'admin', active: true }

Rest-параметры

function sum(...numbers) {
  return numbers.reduce((acc, n) => acc + n, 0);
}

console.log(sum(1, 2, 3, 4)); // 10

Объект arguments

function showArgs() {
  console.log(arguments);        // Arguments(3) [1, 2, 3]
  console.log(arguments.length); // 3
  console.log(arguments[0]);     // 1
}

showArgs(1, 2, 3);

Область видимости

const outer = 'внешняя';

function example() {
  const inner = 'внутренняя';
  console.log(outer); // 'внешняя' — видит внешнюю переменную
  console.log(inner); // 'внутренняя'
}

example;
// console.log(inner); // ReferenceError — не видна снаружи

Function Declaration в блоках

// Поведение зависит от strict mode!
// В strict mode функция видна только внутри блока
'use strict';

if (true) {
  function blockScoped() {
    return 'внутри if';
  }
  console.log(blockScoped); // 'внутри if'
}

// blockScoped; // ReferenceError в strict mode

Именованные функции и отладка

// Имя функции отображается в стеке вызовов
function processPayment(amount) {
  if (amount <= 0) {
    throw new Error('Сумма должна быть положительной');
  }
  // ...
}

// В стеке ошибки будет видно: "at processPayment"
// Это упрощает отладку

Свойство name

function myFunction() {}
console.log(myFunction.name); // "myFunction"

Функция как значение

Даже Function Declaration создаёт объект-функцию, который можно передавать:

function double(x) {
  return x * 2;
}

const numbers = [1, 2, 3];
const doubled = numbers.map(double);
console.log(doubled); // [2, 4, 6]

// Передача как callback
setTimeout(double.bind(null, 5), 1000);

Когда использовать

Ситуация Рекомендация
Основная логика модуля Function Declaration
Нужен hoisting Function Declaration
Утилиты и хелперы Function Declaration
Callback в одну строку Arrow Function
Методы объекта Method shorthand

Частые ошибки

1. Объявление в non-strict блоке

// Без strict mode поведение в блоках непредсказуемо!
if (true) {
  function ambiguous() { return 1; }
}
// Может работать или нет в зависимости от движка
// Решение: используйте let + Function Expression
let safe;
if (true) {
  safe = function { return 1; };
}

2. Забытый return

function getFullName(first, last) {
  `${first} ${last}`; // Строка вычисляется, но не возвращается!
}
console.log(getFullName('Иван', 'Петров')); // undefined

// Правильно:
function getFullName(first, last) {
  return `${first} ${last}`;
}

3. Перезапись функции

function action() { return 'первая'; }
function action() { return 'вторая'; } // Перезаписала первую!

console.log(action); // 'вторая'

Практика

  1. Напиши функцию multiply(a, b), возвращающую произведение двух чисел
  2. Напиши функцию greetAll(...names), которая приветствует каждое имя из списка
  3. Вызови функцию до её объявления — убедись, что hoisting работает
  4. Создай функцию с параметром по умолчанию и вызови её с/без аргумента
  5. Напиши функцию factorial(n), использующую рекурсию

Связанные темы

Ресурсы


🎓 Источник: Функции, стрелочные функции, контексты

  • 📅 2018-09-27 · YouTube · ID: pn5myCmpV2U
  • Тезисы:
    • Function declaration видна сразу везде в файле (hoisting)
    • Function expression — видна только после присваивания
    • Можно вызывать declaration раньше места объявления
    • Это исключительно особенность function declaration
  • Цитата: «Если вы где-нибудь в вашем файле сделали function declaration, то он будет сразу виден во всех частях этого файла.»