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

В чем разница между функциями классическими и стрелочными?

2.2 Middle🔥 171 комментариев
#JavaScript Core

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

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

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

Разница между классическими и стрелочными функциями

Классические функции (function declaration) и стрелочные функции (arrow functions) выглядят похоже, но они имеют важные различия в поведении, особенно в контексте this.

Синтаксис

// Классическая функция
function add(a, b) {
  return a + b;
}

// Стрелочная функция
const add = (a, b) => {
  return a + b;
};

// Стрелочная функция - сокращённая
const add = (a, b) => a + b;

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

Классическая функция имеет свой контекст this, который зависит от способа вызова:

const user = {
  name: "John",
  greet: function() {
    console.log(`Hello, ${this.name}`);
  }
};

user.greet(); // "Hello, John" (this = user)

const greetFunc = user.greet;
greetFunc(); // "Hello, undefined" (this = window/global)

Стрелочная функция ВСЕГДА использует this из окружающего контекста (лексический this):

const user = {
  name: "John",
  greet: () => {
    console.log(`Hello, ${this.name}`);
  }
};

user.greet(); // "Hello, undefined" (this = глобальный объект, не user!)

function User(name) {
  this.name = name;
  
  // Классическая функция - своя this
  this.getName1 = function() {
    return this.name;
  };
  
  // Стрелочная функция - берёт this из конструктора
  this.getName2 = () => {
    return this.name;
  };
}

const john = new User("John");
console.log(john.getName1()); // "John"
console.log(john.getName2()); // "John"

Практический пример: обработчик событий

class Counter {
  constructor() {
    this.count = 0;
  }
  
  // Классическая функция - неправильно!
  incrementWrong() {
    button.addEventListener("click", function() {
      this.count++; // this = button, не Counter!
      console.log(this.count); // undefined++
    });
  }
  
  // Стрелочная функция - правильно!
  incrementRight() {
    button.addEventListener("click", () => {
      this.count++; // this = Counter instance
      console.log(this.count); // 1, 2, 3...
    });
  }
  
  // Классическая функция с .bind() - правильно, но verbose
  incrementBind() {
    button.addEventListener("click", function() {
      this.count++;
      console.log(this.count);
    }.bind(this));
  }
}

Таблица различий

ХарактеристикаКлассическаяСтрелочная
Синтаксисfunction() {}() => {}
Собственный thisДаНет (лексический)
Вызов как конструкторДа (new)Нет
arguments объектДаНет
prototypeДаНет
super, new.targetДаНет
HoistingДа (полный)Нет (как переменная)
Для методов классаНормальноЛучше для callbacks

arguments объект

Классическая функция имеет встроенный arguments:

function sum() {
  console.log(arguments); // [1, 2, 3]
  return Array.from(arguments).reduce((a, b) => a + b);
}

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

Стрелочная функция НЕ имеет arguments, используй rest параметры:

// Неправильно
const sum = () => {
  console.log(arguments); // ReferenceError
};

// Правильно
const sum = (...args) => {
  console.log(args); // [1, 2, 3]
  return args.reduce((a, b) => a + b);
};

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

Hoisting (поднятие)

Классические функции поднимаются полностью:

console.log(typeof greet); // "function" (доступна)

function greet() {
  return "Hello";
}

console.log(greet()); // "Hello"

Стрелочные функции НЕ поднимаются (как переменные):

console.log(typeof greet); // "undefined"

const greet = () => "Hello";

console.log(greet()); // "Hello"

Конструкторы

Классическую функцию можно вызвать с new:

function User(name) {
  this.name = name;
}

const john = new User("John"); // OK
console.log(john.name); // "John"

Стрелочную функцию нельзя вызвать с new:

const User = (name) => {
  this.name = name; // this - из глобального контекста
};

const john = new User("John"); // TypeError: User is not a constructor

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

// Старый подход с классовым компонентом
class Button extends React.Component {
  constructor(props) {
    super(props);
    this.count = 0;
  }
  
  // Нужен .bind() или стрелочная функция
  handleClick = () => {
    // Стрелочная функция - правильно!
    this.count++;
    this.setState({ count: this.count });
  };
  
  // Или классическая с .bind()
  handleClickBind() {
    this.count++;
  }
  
  componentDidMount() {
    // Неправильно без bind
    // button.addEventListener("click", this.handleClickBind);
    
    // Правильно
    button.addEventListener("click", this.handleClickBind.bind(this));
    
    // Или со стрелочной
    button.addEventListener("click", this.handleClick);
  }
  
  render() {
    return <button onClick={this.handleClick}>Click</button>;
  }
}

// Современный подход с функциональным компонентом
function Button() {
  const [count, setCount] = useState(0);
  
  // Стрелочная функция - стандарт в React
  const handleClick = () => {
    setCount(count + 1);
  };
  
  return <button onClick={handleClick}>Count: {count}</button>;
}

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

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

  • Когда нужна своя this (методы объектов)
  • Когда нужны arguments
  • Когда нужен конструктор (new)
  • Для обычных функций, где this не важна
const calculator = {
  value: 0,
  add: function(x) { // классическая, нужна this
    this.value += x;
    return this.value;
  },
  reset: function() {
    this.value = 0;
  }
};

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

  • Для callbacks (обработчики событий)
  • Для методов массива (.map, .filter, .forEach)
  • Когда нужно сохранить this из родительского контекста
  • Для простых функций-преобразований
const numbers = [1, 2, 3, 4, 5];

// Стрелочная функция идеальна для map
const doubled = numbers.map(n => n * 2);

// Обработчик события
button.addEventListener("click", () => {
  console.log("Clicked");
});

// В Promise
fetch("/api/data")
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error));

Вывод

Главное отличие: стрелочные функции используют лексический this, а классические - динамический.

  • Стрелочные функции - лучший выбор в современном JavaScript
  • Классические функции - нужны для конструкторов и методов объектов
  • В React и Promises - стрелочные функции - стандарт
  • Помни про отсутствие arguments и this в стрелочных функциях
В чем разница между функциями классическими и стрелочными? | PrepBro