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

Чем отличаются стрелочные функции от обычных функций в JavaScript?

3.0 Senior🔥 161 комментариев
#DevOps и инфраструктура

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

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

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

Стрелочные функции vs обычные функции в JavaScript

Это важный вопрос, так как стрелочные функции (arrow functions) — это ES6 фича, которая кардинально отличается от обычных функций. Хотя я Python разработчик, JavaScript знаю хорошо, и эти различия критичны при написании фронтенда.

Синтаксис

Обычная функция:

function add(a, b) {
  return a + b;
}

const add = function(a, b) {
  return a + b;
};

Стрелочная функция:

const add = (a, b) => {
  return a + b;
};

// Сокращённый синтаксис (implicit return)
const add = (a, b) => a + b;

// Один параметр без скобок
const square = x => x * x;

Основное отличие: контекст this

Это самое важное отличие! Arrow functions НЕ имеют своего this, они используют this из окружающего контекста.

// Обычная функция: this зависит от способа вызова
const person = {
  name: "Alice",
  greet: function() {
    console.log(this.name); // "Alice" если вызвать person.greet()
  },
  delayedGreet: function() {
    setTimeout(function() {
      console.log(this.name); // undefined! this != person
    }, 1000);
  }
};

person.greet(); // "Alice"
person.delayedGreet(); // undefined

// Arrow function: сохраняет this родителя
const person2 = {
  name: "Bob",
  delayedGreet: function() {
    setTimeout(() => {
      console.log(this.name); // "Bob" - сохранило контекст!
    }, 1000);
  }
};

person2.delayedGreet(); // "Bob"

Таблица отличий

ХарактеристикаОбычная функцияСтрелочная функция
thisЗависит от вызоваИз окружающего контекста
argumentsЕсть встроенный объектНЕТ arguments
newМожно вызвать как конструкторНЕЛЬЗЯ вызвать как конструктор
prototypeЕстьНЕТ
superПоддерживаетсяНЕЛЬЗЯ использовать
СинтаксисДлинныйКраткий

this в различных контекстах

// В методе класса - обычная функция
class Counter {
  constructor() {
    this.count = 0;
  }
  
  increment() {
    this.count++;
  }
  
  // Проблема: setTimeout потеряет контекст
  incrementLater() {
    setTimeout(function() {
      this.count++; // this = undefined!
    }, 1000);
  }
  
  // Решение: arrow function сохраняет this
  incrementLaterFixed() {
    setTimeout(() => {
      this.count++; // this = Counter instance
    }, 1000);
  }
}

arguments vs rest parameters

// Обычная функция имеет встроенный arguments
function sum() {
  let total = 0;
  for (let i = 0; i < arguments.length; i++) {
    total += arguments[i];
  }
  return total;
}

sum(1, 2, 3); // 6

// Arrow function НЕ имеет arguments
const sum2 = () => {
  console.log(arguments); // ReferenceError!
};

// Используем rest parameters (...)
const sum3 = (...args) => {
  return args.reduce((a, b) => a + b, 0);
};

sum3(1, 2, 3); // 6

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

Используй обычную функцию:

  • Конструкторы классов
  • Когда нужен собственный this
  • Методы объектов (если не нужна стрелочная)
  • Функции с arguments

Используй стрелочную функцию:

  • Callbacks (setTimeout, map, filter)
  • В классах для методов, которые нужны как callbacks
  • Когда нужен this из родительского контекста
  • Для коротких операций (implicit return)

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

class Todo {
  constructor() {
    this.items = [];
  }
  
  // Обычная функция - НЕ подходит здесь
  // addLater() {
  //   setTimeout(function() {
  //     this.items.push("new"); // this = undefined
  //   }, 1000);
  // }
  
  // Правильно - стрелочная функция
  addLater() {
    setTimeout(() => {
      this.items.push("new"); // this = Todo instance
    }, 1000);
  }
  
  // Также правильно - bind
  addLaterBind() {
    setTimeout(function() {
      this.items.push("new");
    }.bind(this), 1000);
  }
}

Выводы

Стрелочные функции — это мощный инструмент для упрощения кода и избежания проблем с this. Они идеальны для callbacks, но не подходят для конструкторов и методов, где нужен собственный контекст.