Кратко
this — это специальная переменная, которая ссылается на объект. Какой именно — зависит от того, КАК вызвана функция. Есть 4 правила: default (global/undefined), implicit (obj.method()), explicit (call/apply/bind), new (new Constructor()).
Подробно
Что такое this?
this — это ссылка на объект, но значение this определяется в момент ВЫЗОВА функции, а не в момент объявления.
4 правила определения this:
- Default binding:
function show() { console.log(this); } show(); // window (или undefined в strict mode)
- Implicit binding:
const obj = { name: 'Анна', greet() { console.log(this.name); } }; obj.greet(); // 'Анна' — this = obj
- Explicit binding:
function greet() { console.log(this.name); } const user = { name: 'Пётр' }; greet.call(user); // 'Пётр' — this = user greet.apply(user); // 'Пётр' const bound = greet.bind(user); bound(); // 'Пётр'
- new binding:
function Person(name) { this.name = name; } const p = new Person('Анна'); console.log(p.name); // 'Анна' — this = новый объект
Arrow functions: const obj = { name: 'Анна', greet: () => { console.log(this.name); } }; obj.greet(); // undefined (arrow не создаёт свой this!)
Arrow functions берут this из внешнего lexical scope.
Ментальная модель
this — как зеркало. В зависимости от того, где вы стоите (как вызвали функцию), зеркало отражает разный объект. obj.method() — зеркало смотрит на obj. call(obj) — вы поворачиваете зеркало на obj.
Примеры
**Самый простой:**
const user = {
name: 'Анна',
greet() {
console.log(`Привет, ${this.name}`);
}
};
user.greet(); // 'Привет, Анна'
// this = user (implicit binding)Когда функция вызвана через объект — this ссылается на этот объект.
**Простой:**
function sayHello() {
console.log(`Привет, ${this.name}`);
}
const user1 = { name: 'Анна', greet: sayHello };
const user2 = { name: 'Пётр', greet: sayHello };
user1.greet(); // 'Привет, Анна'
user2.greet(); // 'Привет, Пётр'
// Одна функция — разный this в зависимости от объектаthis определяется в момент вызова, а не объявления.
**Реальный пример:**
const counter = {
count: 0,
start() {
// Arrow function сохраняет this из start
setInterval(() => {
this.count++;
console.log(this.count);
}, 1000);
}
};
// counter.start(); // 1, 2, 3...
// Обычная функция потеряла бы this!Стрелочная функция берёт this из outer scope (start).
Частые ошибки
**Неправильно:** Думать, что this = объект, где объявлена функция
**Почему:** this определяется в момент ВЫЗОВА, а не объявления.
**Правильно:** this зависит от того, КАК функция вызвана, не от того, ГДЕ она написана.
**Неправильно:** Использовать стрелочные функции для методов объекта
**Почему:** Arrow functions не создают свой this. this берётся из внешнего scope.
**Правильно:** Для методов объекта используйте обычные функции или shorthand methods.
**Неправильно:** Потерять this при передаче метода как callback
**Почему:** const fn = obj.greet; fn() — this = undefined (default binding).
**Правильно:** Используйте bind: obj.greet.bind(obj) или arrow function.
Важно запомнить
- this определяется в момент ВЫЗОВА, не объявления
- 4 правила: default, implicit, explicit, new
- Arrow functions НЕ создают свой this
- obj.method() — this = obj (implicit)
- call/apply/bind — явное задание this
Связь
Назад: Вы знаете объекты (J11) и функции (J9) — теперь вы понимаете, как они взаимодействуют.
Вперёд: Следующий урок (JI5) — call, apply, bind подробнее.