Стрелочные функции (Arrow Functions) — это краткий синтаксис для объявления функций, введенный в ES6. Они имеют лексический контекст this
и более компактную запись.
Ключевые отличия от обычных функций:
this
— наследуют контекст от родительской областиnew
arguments
Стрелочные функции — это альтернативный способ записи функций, который появился в ES6 (2015). Они используют символ =>
(“стрелка”) для определения функции.
// Обычная функция
function add(a, b) {
return a + b;
}
// Стрелочная функция
const add = (a, b) => {
return a + b;
};
// Краткая запись (неявный return)
const add = (a, b) => a + b;
const greet = (name) => {
console.log(`Привет, ${name}!`);
return `Добро пожаловать, ${name}!`;
};
// Одно выражение — автоматический return
const double = x => x * 2;
const sum = (a, b) => a + b;
const getMessage = () => "Привет, мир!";
const sayHello = () => "Привет!";
const getRandomNumber = () => Math.random();
// Со скобками
const square = (x) => x * x;
// Без скобок
const square = x => x * x;
// ❌ Неправильно — интерпретируется как блок кода
const createUser = name => { name: name, age: 25 };
// ✅ Правильно — оборачиваем в скобки
const createUser = name => ({ name: name, age: 25 });
const createUser = name => ({ name, age: 25 }); // ES6 shorthand
this
Самое важное отличие — стрелочные функции не имеют собственного this
.
const person = {
name: "Александр",
age: 30,
// Обычная функция — собственный this
regularMethod: function() {
console.log(this.name); // "Александр"
setTimeout(function() {
console.log(this.name); // undefined (this = window/global)
}, 1000);
},
// Стрелочная функция — лексический this
arrowMethod: function() {
console.log(this.name); // "Александр"
setTimeout(() => {
console.log(this.name); // "Александр" (наследует this)
}, 1000);
}
};
// ✅ Работает — function declaration поднимается
console.log(regularFunc()); // "Работает!"
function regularFunc() {
return "Работает!";
}
// ❌ Ошибка — стрелочная функция не поднимается
console.log(arrowFunc()); // ReferenceError
const arrowFunc = () => "Работает!";
// ✅ Обычная функция — можно использовать с new
function Person(name) {
this.name = name;
}
const person1 = new Person("Александр"); // Работает
// ❌ Стрелочная функция — нельзя использовать с new
const PersonArrow = (name) => {
this.name = name;
};
const person2 = new PersonArrow("Мария"); // TypeError
arguments
// ✅ Обычная функция — есть arguments
function regularFunc() {
console.log(arguments); // [1, 2, 3]
}
regularFunc(1, 2, 3);
// ❌ Стрелочная функция — нет arguments
const arrowFunc = () => {
console.log(arguments); // ReferenceError
};
// ✅ Используйте rest параметры
const arrowFuncWithRest = (...args) => {
console.log(args); // [1, 2, 3]
};
arrowFuncWithRest(1, 2, 3);
Особенность | Обычная функция | Стрелочная функция |
---|---|---|
Синтаксис | function() {} | () => {} |
Hoisting | ✅ Да | ❌ Нет |
this | Динамический | Лексический |
new | ✅ Можно | ❌ Нельзя |
arguments | ✅ Есть | ❌ Нет |
super | ✅ Есть | ❌ Нет |
Прототип | ✅ Есть | ❌ Нет |
Генераторы | ✅ Поддерживает | ❌ Не поддерживает |
const numbers = [1, 2, 3, 4, 5];
// Старый способ
const doubled = numbers.map(function(n) {
return n * 2;
});
// Стрелочные функции
const doubled = numbers.map(n => n * 2);
const filtered = numbers.filter(n => n > 3);
const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(filtered); // [4, 5]
console.log(sum); // 15
class Button {
constructor(element) {
this.element = element;
this.clickCount = 0;
// ❌ Проблема с this в обычной функции
this.element.addEventListener('click', function() {
this.clickCount++; // this = element, не Button
console.log(this.clickCount); // NaN
});
// ✅ Стрелочная функция сохраняет this
this.element.addEventListener('click', () => {
this.clickCount++; // this = Button instance
console.log(this.clickCount); // 1, 2, 3...
});
}
}
// Цепочка промисов со стрелочными функциями
fetch('/api/users')
.then(response => response.json())
.then(users => users.filter(user => user.active))
.then(activeUsers => console.log(activeUsers))
.catch(error => console.error(error));
// Async/await со стрелочными функциями
const fetchUsers = async () => {
try {
const response = await fetch('/api/users');
const users = await response.json();
return users.filter(user => user.active);
} catch (error) {
console.error(error);
}
};
const calculator = {
value: 0,
// ✅ Обычная функция для методов
add(num) {
this.value += num;
return this;
},
// ❌ Стрелочная функция — потеря this
multiply: (num) => {
this.value *= num; // this не указывает на calculator
return this;
},
// ✅ Стрелочная функция внутри метода
processArray(numbers) {
return numbers.map(n => n + this.value); // this = calculator
}
};
const obj = {
name: "Александр",
getName: () => {
return this.name;
}
};
console.log(obj.getName());
function Timer() {
this.seconds = 0;
setInterval(() => {
this.seconds++;
console.log(this.seconds);
}, 1000);
}
const timer = new Timer();
const numbers = [1, 2, 3, 4, 5];
const result = numbers
.filter(n => n > 2)
.map(n => n * 2)
.reduce((sum, n) => sum + n);
console.log(result);
const user = {
name: "Александр",
greet() {
console.log(`Привет, ${this.name}!`);
const inner = () => {
console.log(`Внутри: ${this.name}`);
};
inner();
}
};
user.greet();
const greetFunc = user.greet;
greetFunc();
const createMultiplier = (factor) => {
return (number) => number * factor;
};
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5));
console.log(triple(4));
const Person = (name) => {
this.name = name;
};
const person = new Person("Александр");
console.log(person.name);
// 1. Колбэки для массивов
const users = ['Александр', 'Мария', 'Иван'];
const greetings = users.map(name => `Привет, ${name}!`);
// 2. Короткие функции
const isEven = n => n % 2 === 0;
const getFullName = (first, last) => `${first} ${last}`;
// 3. Сохранение контекста this
class Component {
constructor() {
this.state = { count: 0 };
}
handleClick() {
// Стрелочная функция сохраняет this
setTimeout(() => {
this.state.count++;
}, 1000);
}
}
// 4. Функции высшего порядка
const createValidator = (rule) => (value) => rule.test(value);
// 5. Промисы и async/await
const fetchData = async () => {
const response = await fetch('/api/data');
return response.json();
};
// 1. Методы объектов
const obj = {
name: "Александр",
// ❌ Плохо — потеря this
greet: () => {
console.log(`Привет, ${this.name}!`); // undefined
},
// ✅ Хорошо
greet() {
console.log(`Привет, ${this.name}!`);
}
};
// 2. Конструкторы
// ❌ Плохо — не работает
const Person = (name) => {
this.name = name;
};
// ✅ Хорошо
class Person {
constructor(name) {
this.name = name;
}
}
// 3. Методы прототипа
// ❌ Плохо
Person.prototype.greet = () => {
console.log(this.name); // undefined
};
// ✅ Хорошо
Person.prototype.greet = function() {
console.log(this.name);
};
// 4. Event handlers с нужным this
// ❌ Плохо — если нужен this элемента
button.addEventListener('click', () => {
this.style.color = 'red'; // this не button
});
// ✅ Хорошо
button.addEventListener('click', function() {
this.style.color = 'red'; // this = button
});
// ✅ Используйте стрелочные для коротких функций
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
// ✅ Используйте обычные для методов объектов
const user = {
name: "Александр",
greet() {
return `Привет, ${this.name}!`;
}
};
// ✅ Используйте стрелочные для сохранения контекста
class Timer {
constructor() {
this.time = 0;
setInterval(() => {
this.time++; // this = Timer instance
}, 1000);
}
}
Стрелочные функции лучше подходят для простых операций, а обычные функции — для сложной бизнес-логики с множественными условиями и вычислениями.
// ✅ Стрелочные функции отлично работают с деструктуризацией
const users = [
{ name: "Александр", age: 30 },
{ name: "Мария", age: 25 }
];
const names = users.map(({ name }) => name);
const adults = users.filter(({ age }) => age >= 18);
// Создание объектов
const createUser = ({ name, age = 18 }) => ({
name,
age,
id: Math.random()
});
// Простые async стрелочные функции
const fetchUser = async (id) => {
const response = await fetch(`/api/users/${id}`);
return response.json();
};
// В массивах
const userIds = [1, 2, 3];
const users = await Promise.all(
userIds.map(async (id) => {
const user = await fetchUser(id);
return user;
})
);
// Обработка ошибок
const safeAsyncOperation = async () => {
try {
const result = await riskyOperation();
return result;
} catch (error) {
console.error('Ошибка:', error);
return null;
}
};
// Компоненты
const UserCard = ({ name, age }) => (
<div>
<h3>{name}</h3>
<p>Возраст: {age}</p>
</div>
);
// Event handlers
const Button = () => {
const [count, setCount] = useState(0);
// Стрелочная функция сохраняет контекст
const handleClick = () => {
setCount(prev => prev + 1);
};
return <button onClick={handleClick}>{count}</button>;
};
// useEffect
useEffect(() => {
const timer = setInterval(() => {
console.log('Таймер сработал');
}, 1000);
return () => clearInterval(timer);
}, []);
// ❌ Ошибка
const obj = {
name: "Александр",
greet: () => console.log(this.name) // undefined
};
// ✅ Исправление
const obj = {
name: "Александр",
greet() {
console.log(this.name); // "Александр"
}
};
// ❌ Ошибка — интерпретируется как блок кода
const createUser = name => { name: name, age: 25 };
// ✅ Исправление — оборачиваем в скобки
const createUser = name => ({ name: name, age: 25 });
// ❌ Ошибка
const Person = (name) => {
this.name = name;
};
const person = new Person("Александр"); // TypeError
// ✅ Исправление
class Person {
constructor(name) {
this.name = name;
}
}
Стрелочные функции — это мощный инструмент ES6, который:
Преимущества:
Ограничения:
Когда использовать:
map
, filter
, reduce
)this
this
Понимание стрелочных функций — это ключ к современному JavaScript и функциональному программированию!
Хочешь больше статей по подготовке к собеседованию? Подпишись на EasyAdvice(@AleksandrEmolov_EasyAdvice), добавляй сайт в избранное и прокачивай себя каждый день 💪