Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как работает This в JavaScript
Это один из самых запутанных концептов. Расскажу точно как it работает.
Что такое This?
this - это ключевое слово которое ссылается на объект КОНТЕКСТА (context) где выполняется функция.
// This зависит от ТО КАК вызвана функция, а не ГДЕ она определена!
const obj = {
name: 'Объект',
getName: function() {
console.log(this.name);
}
};
obj.getName(); // this = obj -> "Объект"
const fn = obj.getName;
fn(); // this = window (или undefined в strict mode) -> undefined
1. Method Call (this = объект)
const person = {
name: 'John',
greet: function() {
console.log('Привет, ' + this.name);
}
};
person.greet(); // "Привет, John"
// this = person
2. Function Call (this = window или undefined)
function sayName() {
console.log(this.name);
}
sayName(); // this = window (в браузере)
// В строгом режиме: this = undefined
// Strict mode
'use strict';
function sayName() {
console.log(this); // undefined
}
sayName();
3. Constructor (this = новый объект)
function Person(name) {
this.name = name; // this указывает на новый объект
}
const john = new Person('John');
console.log(john.name); // "John"
// this = john (новый объект)
4. Arrow Function (this из родительской области)
const obj = {
name: 'Объект',
// Обычная функция
method1: function() {
console.log(this.name); // "Объект"
},
// Arrow function - наследует this от родительской области
method2: () => {
console.log(this.name); // undefined (this = window)
}
};
obj.method1(); // this = obj
obj.method2(); // this = window
// Arrow functions НЕ имеют своего this!
5. Явное управление This (call, apply, bind)
call() - вызвать с явным this
function greet(greeting, punctuation) {
console.log(greeting + ', ' + this.name + punctuation);
}
const person = { name: 'John' };
greet.call(person, 'Привет', '!');
// this = person
// Вывод: "Привет, John!"
apply() - как call но аргументы в массиве
greet.apply(person, ['Привет', '!']);
// this = person
// Вывод: "Привет, John!"
bind() - создать новую функцию с фиксированным this
const boundGreet = greet.bind(person, 'Привет');
boundGreet('!'); // "Привет, John!"
// bind возвращает новую функцию, не вызывает её
// Это это очень важно!
Практические примеры
Пример 1: Event Handler
// ПЛОХО - this потеряется
const button = document.querySelector('button');
const component = {
count: 0,
increment: function() {
this.count++; // ПЛОХО: this будет кнопка, не component!
}
};
button.addEventListener('click', component.increment);
// ХОРОШО - используй bind
button.addEventListener('click', component.increment.bind(component));
// ХОРОШО - используй arrow function
button.addEventListener('click', () => component.increment());
Пример 2: React класс
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
// ВАРИАНТ 1: bind в конструкторе
this.increment = this.increment.bind(this);
}
// ВАРИАНТ 2: arrow function (автоматический bind)
increment = () => {
this.setState({ count: this.state.count + 1 });
}
// ВАРИАНТ 3: bind в JSX
render() {
return (
<button onClick={this.increment}>Увеличить</button>
);
}
}
// ПЛОХО - this потеряется
class Counter extends React.Component {
increment() {
// this будет undefined
this.setState({ count: this.state.count + 1 });
}
render() {
return <button onClick={this.increment}>Увеличить</button>;
}
}
Пример 3: this в методах
const obj = {
name: 'Объект',
delay: function() {
console.log(this.name); // "Объект"
// ПЛОХО - в callback this будет другой
setTimeout(function() {
console.log(this.name); // undefined!
}, 1000);
},
delayFixed: function() {
console.log(this.name); // "Объект"
// ХОРОШО - arrow function сохраняет this
setTimeout(() => {
console.log(this.name); // "Объект"
}, 1000);
}
};
obj.delay(); // undefined
obj.delayFixed(); // "Объект"
Визуализация правила this
Что вызвало функцию? | Значение this
─────────────────────┼──────────────────────
obj.method() | obj
function() | window (или undefined)
new Constructor() | новый объект
arrow function | родительская область
fn.call(obj, ...) | obj (явное)
fn.apply(obj, ...) | obj (явное)
fn.bind(obj) | obj (явное, новая функция)
event.target.onclick | event.target
Распространённые ошибки
Ошибка 1: this в обычной функции
const user = {
name: 'John',
sayHi: function() {
console.log(this.name); // "John" ✓
function inner() {
console.log(this.name); // undefined ✗
}
inner();
}
};
// Решение - сохрани this
const user = {
name: 'John',
sayHi: function() {
const self = this; // или const that = this
function inner() {
console.log(self.name); // "John" ✓
}
inner();
}
};
// Или используй arrow function
const user = {
name: 'John',
sayHi: function() {
const inner = () => {
console.log(this.name); // "John" ✓
};
inner();
}
};
Ошибка 2: this в setTimeout
// ПЛОХО
const obj = {
count: 0,
start: function() {
setTimeout(function() {
this.count++; // ОШИБКА: this = window
}, 1000);
}
};
// ХОРОШО
const obj = {
count: 0,
start: function() {
setTimeout(() => {
this.count++; // this = obj ✓
}, 1000);
}
};
Ошибка 3: this потеряется при деструктуризации
const obj = {
name: 'John',
greet: function() {
console.log('Привет, ' + this.name);
}
};
const { greet } = obj;
greet(); // ОШИБКА: this = undefined
// Решение
const { greet } = obj;
greet.call(obj); // ✓
// Или bind сразу
const { greet } = { ...obj };
const boundGreet = greet.bind(obj);
boundGreet(); // ✓
Дебаг this
function myFunction() {
console.log('this =', this);
console.log('type of this =', typeof this);
console.log('constructor =', this.constructor.name);
}
myFunction(); // this = Window
const obj = { myFunction };
obj.myFunction(); // this = Object
const arrow = () => {
console.log('this =', this); // наследует this из родителя
};
Чеклист
[ ] Понял я как вызвана функция?
[ ] Это метод объекта? -> this = объект
[ ] Это просто функция? -> this = window (undefined в strict)
[ ] Это конструктор? -> this = новый объект
[ ] Это arrow function? -> this из родителя
[ ] Явно передан this (call/apply/bind)? -> переданный this
[ ] Это event handler? -> this = element
[ ] Потеряется ли this в callback? -> используй arrow function
Итого
this определяется КАК вызвана функция:
- Method call (obj.method()) -> this = obj
- Function call (func()) -> this = window (undefined)
- Constructor (new Func()) -> this = новый объект
- Arrow function (() => {}) -> this из родителя
- call/apply/bind (func.call(obj)) -> this = obj
Практический совет:
- В event handlers используй arrow functions
- В классах React используй arrow functions для методов
- Если потеряется this - используй bind или arrow function
- Arrow functions часто спасают ситуацию!