Контекст выполнения (this) — одна из ключевых концепций в JavaScript, вызывающая много вопросов у разработчиков. Давайте разберемся, что же такое this, как он определяется и как использовать его возможности в своем коде.
Что такое this
В JavaScript ключевое слово this ссылается на некий объект, который называется контекстом выполнения. Фактически, this — это способ передать контекст в функцию или метод, чтобы они могли работать с данными этого контекста.
Значение this определяется тем, как и где была вызвана функция, а не тем, где она была объявлена. Одна и та же функция, вызванная в разных контекстах, будет иметь разное значение this.
Глобальный контекст
В глобальной области видимости (вне функций) this ссылается на глобальный объект. В браузере это будет объект window:
console.log(this === window); // true
this.foo = "bar";
console.log(window.foo); // "bar"
Контекст внутри функции
Внутри обычной функции (не стрелочной) значение this по умолчанию также будет ссылаться на глобальный объект:
function f() {
console.log(this === window);
}
f(); // true
Однако, если включен строгий режим («use strict»), то this внутри функции будет undefined:
function f() {
"use strict";
console.log(this); // undefined
}
f();
Контекст в методах объекта
Когда функция вызывается как метод объекта через точку obj.method(), this внутри этой функции будет ссылаться на сам объект obj:
const user = {
name: "John",
greet() {
console.log(this.name);
}
};
user.greet(); // "John"
Здесь this.name внутри метода greet() ссылается на свойство name объекта user.
Важно понимать, что не имеет значения, где объявлен метод. Контекст определяется в момент вызова. Если тот же метод вызвать без объекта, this уже не будет ссылаться на объект:
const greet = user.greet;
greet(); // undefined
Явное указание контекста
Функции в JavaScript имеют специальные методы call, apply и bind, которые позволяют явно задать контекст выполнения this.
Методы call и apply вызывают функцию, первым аргументом передавая объект, который будет использоваться как this. Отличаются они синтаксисом передачи остальных аргументов:
function greet(phrase) {
console.log(`${phrase}, ${this.name}!`);
}
const user = { name: "John" };
greet.call(user, "Hello"); // Hello, John!
greet.apply(user, ["Hello"]); // Hello, John!
Метод bind создает новую функцию с привязанным контекстом. Он не вызывает функцию сразу, а возвращает новую, которую можно вызвать позже:
const greetJohn = greet.bind(user, "Hello");
greetJohn(); // Hello, John!
Стрелочные функции
У стрелочных функций нет своего this. Они берут значение this из окружающего кода.
const user = {
name: "John",
greetArrow: () => {
console.log(this.name); // undefined
},
greetFunc: function() {
console.log(this.name); // "John"
}
};
Здесь стрелочная функция greetArrow не имеет своего контекста и this в ней ссылается на глобальный объект. А обычная функция greetFunc при вызове как метод объекта имеет контекст этого объекта.
Это свойство стрелочных функций удобно использовать для сохранения контекста:
const user = {
name: "John",
greet() {
setTimeout(() => {
console.log(this.name); // "John"
}, 1000);
}
};
Стрелочная функция внутри setTimeout сохраняет контекст метода greet, поэтому может обратиться к this.name.
Заключение
Ключевое слово this в JavaScript используется для передачи контекста выполнения в функции и методы. Значение this зависит от того, как была вызвана функция:
- В глобальной области this — это глобальный объект
- В функции this по умолчанию глобальный объект, а в строгом режиме — undefined
- В методах объекта this ссылается на сам объект
- Методы call, apply, bind явно задают контекст
- Стрелочные функции не имеют своего this, а берут его из окружающего кода
Понимание того, как работает контекст выполнения, позволяет писать более гибкий и переиспользуемый код на JavaScript. Главное — всегда отслеживать, чему равен this в данный момент, и при необходимости явно привязывать нужный контекст.