← Назад к вопросам
Есть ли собственный this у стрелочной функции?
1.0 Junior🔥 251 комментариев
#JavaScript Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Стрелочные функции и this: правда и мифы
Короткий ответ: Нет, стрелочные функции НЕ имеют собственного this. Они наследуют this из окружающего контекста во время определения функции (lexical this).
Различие между обычной функцией и стрелочной
Обычная функция (имеет собственный this)
const person = {
name: 'Alice',
sayName: function() {
console.log(this.name); // this зависит от того, как вызвана функция
}
};
person.sayName(); // 'Alice' (this === person)
const sayName = person.sayName;
sayName(); // undefined (this === window или undefined в strict mode)
// this потеряется при передаче функции
const boundSayName = person.sayName.bind(person);
boundSayName(); // 'Alice' (bind установил this)
Стрелочная функция (наследует this)
const person = {
name: 'Bob',
sayName: () => {
// this наследуется из окружающего контекста
// Окружающий контекст = global object (window)
console.log(this.name); // undefined (this === window)
}
};
person.sayName(); // undefined (НЕ Bob!)
// В стрелочной функции this НЕ меняется при вызове
// Правильно для методов объекта:
const person2 = {
name: 'Bob',
sayName() { // Используй обычный метод
console.log(this.name); // 'Bob'
}
};
person2.sayName(); // 'Bob'
Как работает this в стрелочных функциях
Правило: Lexical This
// this в стрелочной функции = this в окружающем scope
const obj = {
value: 42,
createArrow: function() {
// В этом месте this === obj
return () => {
// Стрелочная функция наследует this === obj
console.log(this.value);
};
}
};
const arrow = obj.createArrow();
arrow(); // 42 (this всё ещё obj, даже вне методе)
// Сравни с обычной функцией:
const obj2 = {
value: 42,
createFunc: function() {
return function() {
console.log(this.value); // undefined (this потеряется)
};
}
};
const func = obj2.createFunc();
func(); // undefined
Вложенные контексты
const app = {
title: 'MyApp',
users: ['Alice', 'Bob'],
// Обычный метод
showUsers: function() {
console.log(this.title); // 'MyApp' (this === app)
// Обычная функция в callback-е
this.users.forEach(function(user) {
console.log(user, this.title);
// undefined undefined (потеря this)
});
// Стрелочная функция в callback-е
this.users.forEach(user => {
console.log(user, this.title);
// 'Alice MyApp', 'Bob MyApp' (наследует this из showUsers)
});
}
};
app.showUsers();
// Классическая проблема: потеря this при передаче callback-ов
// Решение: стрелочные функции!
Практические примеры
1. Обработчики событий в React
class Button extends React.Component {
constructor(props) {
super(props);
this.state = { clicked: false };
}
// БЕЗ стрелочной функции нужен bind
handleClickBad() {
// this будет undefined, если не забиндить
this.setState({ clicked: true });
}
// Решение 1: bind в конструкторе
constructor(props) {
super(props);
this.handleClickGood = this.handleClickGood.bind(this);
}
handleClickGood() {
this.setState({ clicked: true });
}
// Решение 2: class field со стрелочной (РЕКОМЕНДУЕТСЯ)
handleClickBest = () => {
// this наследуется из класса, всегда работает
this.setState({ clicked: true });
};
render() {
return (
<button onClick={this.handleClickBest}>
Click me
</button>
);
}
}
2. Асинхронные операции
const api = {
baseURL: 'https://api.example.com',
// БЕЗ стрелочной функции
fetchDataBad: function(id) {
fetch(`${this.baseURL}/users/${id}`)
.then(function(response) {
// this потеряется
return response.json();
})
.then(function(data) {
console.log(this.baseURL); // undefined!
});
},
// СО стрелочной функцией
fetchDataGood: function(id) {
fetch(`${this.baseURL}/users/${id}`)
.then(response => response.json())
.then(data => {
console.log(this.baseURL); // 'https://api.example.com'
});
}
};
api.fetchDataGood(1); // Работает!
3. setTimeout и this
const timer = {
seconds: 0,
// БЕЗ стрелочной функции
startBad: function() {
setInterval(function() {
console.log(this.seconds++); // undefined, this потеряется
}, 1000);
},
// СО стрелочной функцией
startGood: function() {
setInterval(() => {
console.log(this.seconds++); // Работает!
}, 1000);
}
};
timer.startGood();
// 0
// 1
// 2
// ...
call(), apply(), bind() с стрелочными функциями
const person = {
name: 'Alice'
};
const regular = function() {
console.log(this.name);
};
const arrow = () => {
console.log(this.name);
};
// call() и apply() РАБОТАЮТ для обычных функций
regular.call(person); // 'Alice'
regular.apply(person); // 'Alice'
// call() и apply() НЕ РАБОТАЮТ для стрелочных!
const globalName = 'Global';
arrow.call(person); // 'Global' (игнорирует person)
arrow.apply(person); // 'Global' (игнорирует person)
// bind() работает, но не меняет this
const boundArrow = arrow.bind(person);
boundArrow(); // 'Global' (bind не поможет)
// this в стрелочной функции зафиксирована на момент определения
// и её нельзя изменить никакими методами
Когда НЕ использовать стрелочные функции
1. Методы объектов
// Плохо
const calculator = {
value: 0,
add: (n) => {
this.value += n; // this не будет калькулятором
return this.value; // undefined
}
};
calculator.add(5); // undefined
// Хорошо
const calculator = {
value: 0,
add(n) {
this.value += n;
return this.value;
}
};
calculator.add(5); // 5
2. Конструкторы
// Плохо: стрелочные функции не могут быть конструкторами
const User = (name) => {
this.name = name;
};
const user = new User('Alice'); // TypeError!
// Хорошо
class User {
constructor(name) {
this.name = name;
}
}
const user = new User('Alice'); // OK
3. Динамический this
// Если нужен динамический this
const obj = {
value: 1,
getValue: function() {
// this зависит от того, как вызвана функция
return this.value;
}
};
obj.getValue(); // 1
const getValue = obj.getValue;
getValue.call({ value: 100 }); // 100 (можем изменить this)
// Со стрелочной это невозможно
4. prototype и this
// Плохо
const MyClass = function() {
this.value = 1;
};
MyClass.prototype.increment = () => {
this.value++; // this будет global, не экземпляр
};
const instance = new MyClass();
instance.increment(); // this.value остаётся 1
// Хорошо
MyClass.prototype.increment = function() {
this.value++; // this === instance
};
instance.increment(); // this.value === 2
Современный подход: класс + стрелочные
class TodoList {
items: string[] = [];
// Обычный метод
addItem(item: string) {
this.items.push(item);
}
// Class field со стрелочной для callback-ов
handleClick = (id: number) => {
console.log('clicked', id);
// this всегда будет экземпляром TodoList
};
// Использование в React
render() {
return (
<div>
{this.items.map((item, i) => (
// this.handleClick уже забинден правильно
<button key={i} onClick={this.handleClick}>
{item}
</button>
))}
</div>
);
}
}
Хитрости с this
// Проверить значение this
function whatIsThis() {
console.log(this);
}
whatIsThis(); // window (или undefined в strict mode)
whatIsThis.call({ custom: 'object' }); // { custom: 'object' }
// Стрелочная всегда показывает глобальный контекст
const arrowThis = () => {
console.log(this); // window всегда
};
arrow.call({ custom: 'object' }); // window (игнорирует call)
// Проверить, есть ли собственный this
console.log(whatIsThis.hasOwnProperty('this')); // false
// this — это не свойство, это ключевое слово
Итог
Стрелочные функции НЕ имеют собственного this:
- Lexical this — наследуют из окружающего контекста
- Нельзя изменить call(), apply(), bind()
- Хороши для callback-ов — solve "this" binding problem
- Плохи для методов объектов — используй обычные методы
- Нельзя использовать как конструкторы — new стрелочная() выбросит ошибку
Практическое правило:
- Используй стрелочные функции для callback-ов, обработчиков, map/filter
- Используй обычные методы (function или class методы) для методов объектов
- В классах используй class fields со стрелочными для обработчиков событий