← Назад к вопросам

В чем разница между разными видами функций?

2.0 Middle🔥 191 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между разными видами функций в JavaScript

В JavaScript существует несколько способов объявления функций, каждый с особенностями и разными значениями контекста this, hoisting и использования.

1. Объявление функции (Function Declaration)

Function Declaration - это классический способ объявления именованной функции.

Особенности:

  • Поднимается (hoisting) на верх области видимости
  • Может быть вызвана до объявления
  • Создает собственный контекст this
  • Имеет свойство name
// Function Declaration
function greet(name) {
  console.log('Привет, ' + name);
  return name;
}

// Можно вызвать ДО объявления (благодаря hoisting)
greet('Alice');

function greet(name) {
  console.log('Привет, ' + name);
  return name;
}

2. Функциональное выражение (Function Expression)

Function Expression - это функция, присвоенная переменной.

Особенности:

  • НЕ поднимается (не hoisting для значения)
  • Переменная поднимается, но значение undefined
  • Может быть именованной или анонимной
  • Создает собственный контекст this
// Function Expression (анонимная)
const greet = function(name) {
  console.log('Привет, ' + name);
};

// Function Expression (именованная)
const greet = function sayHello(name) {
  console.log('Привет, ' + name);
  // sayHello доступна только внутри функции
};

// Это вызовет ошибку! greet еще undefined
// greet('Alice');

const greet = function(name) {
  console.log('Привет, ' + name);
};

greet('Alice'); // теперь работает

3. Стрелочная функция (Arrow Function)

Arrow Function - современный способ с синтаксисом стрелки =>.

Особенности:

  • НЕ имеет своего контекста this - наследует из родительской области
  • НЕ имеет arguments
  • НЕ может быть конструктором (no new)
  • Более компактный синтаксис
  • Может иметь неявный return для однострочного кода
// Arrow Function - базовый синтаксис
const greet = (name) => {
  console.log('Привет, ' + name);
};

// Однострочная с неявным return
const add = (a, b) => a + b;
console.log(add(2, 3)); // 5

// Одиночный параметр без скобок
const double = x => x * 2;
console.log(double(5)); // 10

// Возвращаем объект - нужны скобки
const createUser = (name) => ({ name, age: 30 });
console.log(createUser('John')); // { name: 'John', age: 30 }

Разница в контексте this

Это самая важная разница:

const user = {
  name: 'John',
  
  // Function Declaration
  greetDecl: function() {
    console.log('Declaration: ' + this.name);
  },
  
  // Function Expression
  greetExpr: function() {
    console.log('Expression: ' + this.name);
  },
  
  // Arrow Function
  greetArrow: () => {
    console.log('Arrow: ' + this.name);
  }
};

user.greetDecl();  // 'Declaration: John' - this = user
user.greetExpr();  // 'Expression: John' - this = user
user.greetArrow(); // 'Arrow: undefined' - this = window/global

Hoisting

// Function Declaration - полностью поднимается
console.log(typeof sayHello); // 'function'
sayHello('Alice');             // работает!

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

// Function Expression - только переменная поднимается
console.log(typeof sayBye); // 'undefined'
// sayBye('Alice');         // ReferenceError!

const sayBye = function(name) {
  console.log('До свидания, ' + name);
};

// Arrow Function - только переменная поднимается
console.log(typeof wave); // 'undefined'
// wave();                // ReferenceError!

const wave = () => {
  console.log('Помахал рукой');
};

4. Методы объекта

const calculator = {
  value: 10,
  
  // Как Function Declaration
  add(x) {
    this.value += x;
    return this.value;
  },
  
  // Как Function Expression
  multiply: function(x) {
    this.value *= x;
    return this.value;
  },
  
  // Arrow Function - неправильно!
  // this будет window, не calculator
  subtract: (x) => {
    this.value -= x;  // неправильный this!
  }
};

calculator.add(5);      // 15
calculator.multiply(2); // 30

5. Функция-конструктор

Может быть только Function Declaration или Function Expression:

// Function Declaration как конструктор
function User(name, age) {
  this.name = name;
  this.age = age;
}

const user1 = new User('Alice', 25);
console.log(user1.name); // 'Alice'

// Function Expression как конструктор
const Product = function(title, price) {
  this.title = title;
  this.price = price;
};

const prod = new Product('Ноутбук', 50000);
console.log(prod.title); // 'Ноутбук'

// Arrow Function НЕ может быть конструктором!
const BadConstructor = (name) => {
  this.name = name;
};

const obj = new BadConstructor('test'); // TypeError!

6. Конкурренция функций в событиях

const button = document.querySelector('button');
const obj = {
  count: 0,
  
  // Function Declaration - this = button
  clickDecl: function() {
    this.count++;
    console.log(this); // кнопка
  },
  
  // Arrow Function - this = obj
  clickArrow: () => {
    this.count++;
    console.log(this); // obj
  }
};

button.addEventListener('click', obj.clickDecl);  // this = button
button.addEventListener('click', obj.clickArrow);  // this = obj

Сравнительная таблица

ПараметрFunction DeclFunction ExprArrow Function
HoistingПолныйПеременнаяПеременная
Контекст thisСобственныйСобственныйНаследованный
Аргументы argumentsЕстьЕстьНет
Конструктор (new)ДаДаНет
КомпактностьНетНетДа
Неявный returnНетНетДа

Практические примеры

Фильтрация массива

const numbers = [1, 2, 3, 4, 5];

// Arrow Function - идеально для callback'ов
const doubled = numbers.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]

const even = numbers.filter(n => n % 2 === 0);
console.log(even); // [2, 4]

Класс с методами

class User {
  constructor(name) {
    this.name = name;
  }
  
  // Используем Function Declaration синтаксис
  getName() {
    return this.name;
  }
  
  // Arrow Function для callback'ов
  getData = () => {
    return { name: this.name };
  };
}

const user = new User('Alice');
console.log(user.getName());  // 'Alice'
console.log(user.getData()); // { name: 'Alice' }

Promise цепочка

fetch('/api/user')
  .then(response => response.json())
  .then(data => {
    console.log(data);
    return data.id;
  })
  .then(id => fetch(`/api/user/${id}`))
  .catch(error => console.error('Error:', error));

// Arrow Function идеальна для promise chains

Рекомендации по использованию

Function Declaration - для основных функций, которые нужны везде:

function validateEmail(email) { ... }
function formatDate(date) { ... }

Function Expression - когда функция используется как значение:

const handler = function() { ... };
const callbacks = [function() { ... }];

Arrow Function - для callback'ов, когда нужен контекст родителя:

array.map(item => item.name)
button.addEventListener('click', () => { ... })
promise.then(result => { ... })

Заключение

  • Function Declaration - классический способ, полный hoisting
  • Function Expression - гибкость, контроль over execution
  • Arrow Function - современный, компактный, идеален для callback'ов

Выбирайте в зависимости от контекста и потребностей контекста this.