$ sudo teach IT
РАЗДЕЛ 6 · УРОК 4

Стрелочные функции

Стрелочные функции (arrow functions) — одно из самых популярных нововведений ES6. Они не просто короче — у них есть особое поведение, которое делает их незаменимыми в одних ситуациях и непригодными в других.

⏱ ~25 минут 🎓 Для новичков 🟡 JavaScript ES6

🎯 Зачем появились стрелочные функции?

В JavaScript функции очень часто используются как аргументы других функций (колбэки). Например, методы массивов forEach, map, filter — все принимают функцию. До ES6 это выглядело многословно:

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

// Старый способ — function expression
let doubled = numbers.map(function(n) {
  return n * 2;
});

// Ещё один колбэк
numbers.forEach(function(num) {
  console.log(num);
});

Писать function, потом return ради простого умножения — многовато. ES6 предложил компактный синтаксис стрелочных функций:

// Со стрелочными функциями — гораздо лаконичнее
let doubled = numbers.map(n => n * 2);

numbers.forEach(num => console.log(num));

Разберём синтаксис подробно.

📝 Три формы записи стрелочной функции

В зависимости от сложности тела функции используют разные формы записи. От самой подробной к самой краткой:

Форма 1: Полная запись (несколько строк)

Когда тело функции содержит несколько строк кода — нужны фигурные скобки и явный return. Почти как обычная функция, только без слова function.

const multiply = (a, b) => {
  let result = a * b;
  console.log("Умножаем:", a, "×", b, "=", result);
  return result;
};

multiply(4, 5); // Умножаем: 4 × 5 = 20

Форма 2: Однострочная с return (неявный return)

Если тело функции — одно выражение, можно убрать фигурные скобки и return. Функция автоматически вернёт значение этого выражения. Это называется неявный return.

// Полная форма:
const multiply = (a, b) => { return a * b; };

// Краткая форма (неявный return):
const multiply = (a, b) => a * b;

// Использование:
console.log(multiply(4, 5)); // 20

⚠️ Важно: убрал фигурные скобки — убирай и return. Нельзя писать => return a * b — это синтаксическая ошибка.

Форма 3: Один параметр — без скобок

Если у функции ровно один параметр — скобки вокруг него можно опустить. Это самая короткая форма записи.

// С одним параметром скобки необязательны:
const double = n => n * 2;
const greet = name => "Привет, " + name + "!";
const square = x => x * x;

console.log(double(5));      // 10
console.log(greet("Иван"));  // "Привет, Иван!"
console.log(square(4));      // 16

// Ноль параметров — скобки обязательны:
const getRandomNumber = () => Math.random();
const sayHi = () => "Привет!";

// Два и больше параметров — скобки обязательны:
const add = (a, b) => a + b;
const max = (a, b) => (a > b ? a : b);

⚠️ Особый случай — возврат объекта: если нужно вернуть объектный литерал в краткой форме, нужно обернуть его в скобки. Иначе фигурные скобки объекта воспримутся как тело функции.

// ❌ ОШИБКА: {} воспринимается как тело функции
const makeUser = (name, age) => { name: name, age: age };

// ✅ ПРАВИЛЬНО: оборачиваем объект в ()
const makeUser = (name, age) => ({ name: name, age: age });

console.log(makeUser("Иван", 25)); // { name: "Иван", age: 25 }

🔄 Стрелочные функции в колбэках — их стихия

Стрелочные функции особенно выразительны в роли колбэков для методов массивов. Сравните:

let people = [
  { name: "Иван", age: 25 },
  { name: "Мария", age: 30 },
  { name: "Алекс", age: 22 },
  { name: "Ольга", age: 28 }
];

// Обычный способ (verbose):
let adults = people.filter(function(person) {
  return person.age >= 25;
});

let names = adults.map(function(person) {
  return person.name;
});

// Со стрелочными (чисто и кратко):
let adults = people.filter(person => person.age >= 25);
let names = adults.map(person => person.name);

console.log(names); // ["Иван", "Мария", "Ольга"]

// Можно даже в цепочку:
let result = people
  .filter(p => p.age >= 25)
  .map(p => p.name)
  .sort();

console.log(result); // ["Иван", "Мария", "Ольга"]

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

Это самое важное техническое отличие стрелочных функций от обычных. Тему this мы разберём подробно в следующих разделах, но базовый смысл объяснить нужно уже сейчас.

У обычной функции есть своё this — ключевое слово, которое указывает на «хозяина» функции (объект, от имени которого она вызвана). У стрелочных функций своего this нет — они «заимствуют» this из окружающего контекста.

// Упрощённый пример: timer в объекте
const counter = {
  value: 0,
  start: function() {
    // Обычная функция внутри setInterval имеет своё this
    // которое НЕ является counter — это undefined или window
    setInterval(function() {
      this.value++; // ❌ this здесь = undefined (или window)
      console.log(this.value);
    }, 1000);
  }
};

const counter2 = {
  value: 0,
  start: function() {
    // Стрелочная функция берёт this из start() — это counter2
    setInterval(() => {
      this.value++; // ✅ this здесь = counter2
      console.log(this.value);
    }, 1000);
  }
};

🧭 Практическое правило когда что использовать:
→ Колбэки (forEach, map, filter, setTimeout) → стрелочные функции
→ Методы объектов (функции внутри объекта) → обычные функции
→ Конструкторы (создание объектов через new) → обычные функции

🚫 Когда стрелочные функции не подходят

❌ Методы объектов

Стрелочная функция как метод объекта не получит правильный this — не сможет обратиться к свойствам объекта.

❌ Конструкторы (new)

Стрелочные функции нельзя вызывать через new. Попытка создать объект через стрелочную функцию — ошибка.

❌ Обработчики событий (иногда)

Когда нужно чтобы this указывал на DOM-элемент — используй обычную функцию. Стрелочная возьмёт this из внешнего контекста.

// ❌ Метод объекта — стрелочная не подходит
const person = {
  name: "Иван",
  greet: () => {
    // this здесь — не person! (нет своего this)
    console.log("Привет, " + this.name); // undefined
  }
};

// ✅ Метод объекта — обычная функция правильно
const person = {
  name: "Иван",
  greet: function() {
    console.log("Привет, " + this.name); // "Привет, Иван"
  }
};

✅ Итоги урока

  • Стрелочные функции — компактный синтаксис ES6: const f = (x) => x * 2
  • Три формы: полная (с {} и return), без {} (неявный return), без скобок (один параметр)
  • Неявный return: нет фигурных скобок — нет ключевого слова return
  • Возврат объекта в краткой форме: оборачивай в круглые скобки => ({ key: value })
  • Главное отличие: нет своего this — берут его из внешнего контекста
  • Стрелочные идеальны для колбэков (map, filter, forEach, setTimeout)
  • Не используй стрелочные для методов объектов и конструкторов

В следующем уроке поговорим об области видимости переменных и hoisting — явлении «поднятия», из-за которого функции можно вызывать до их объявления. 🚀

Тест: Стрелочные функции

7 вопросов

Удвоение чисел через стрелочную функцию

Напишите стрелочную функцию double, которая принимает число и возвращает его удвоенное значение. Затем напишите стрелочную функцию doubleArray, которая принимает массив чисел и возвращает новый массив с удвоенными значениями, используя map и стрелочную функцию.

Фильтрация через стрелочную функцию

Напишите стрелочную функцию getAdults, которая принимает массив объектов { name, age } и возвращает массив имён пользователей старше 18 лет. Используйте цепочку filter и map со стрелочными функциями в одну строку.