Ключевое слово this

Free Preview
Продолжительность: 12 мин

Если замыкания — одна из частых тем для обсуждения в JavaScript, то this — пожалуй, самая. Новичкам this кажется непредсказуемым, опытные разработчики знают, что у него есть чёткие правила. Давайте разберёмся.

Контекст выполнения

Каждый раз, когда JavaScript выполняет код, он создаёт контекст выполнения (execution context) — среду, в которой этот код запускается. В этой среде хранятся переменные, область видимости и то, на что указывает this.

Не нужно держать в голове всю механику контекстов — достаточно понять одну вещь: значение this зависит от того, как была вызвана функция.

this в методе объекта

Самый понятный случай: когда функция является методом объекта, this указывает на этот объект:

const city = {
  name: 'Санкт-Петербург',
  greet() {
    console.log(`Добро пожаловать в ${this.name}!`);
  },
};

city.greet(); // Добро пожаловать в Санкт-Петербург!
js

Здесь this — это city, потому что метод greet был вызван через city.greet().

this в обычной функции

В обычной функции, вызванной без объекта, значение this зависит от режима. В нестрогом режиме это глобальный объект (window в браузере), в строгом ('use strict') — undefined:

function showThis() {
  console.log(this);
}

showThis(); // window (в браузере)
js

На практике вызывать функции так и работать с this внутри них — не лучшая идея. Это частый источник ошибок.

this в стрелочных функциях

Стрелочные функции ведут себя иначе: у них нет собственного this. Вместо этого они берут this из окружающей области видимости (помните лексическую область видимости из прошлого урока?):

const city = {
  name: 'Санкт-Петербург',
  logWithDelay() {
    setTimeout(() => {
      console.log(this.name); // this здесь — city, как в родительском методе
    }, 1000);
  },
};

city.logWithDelay(); // Санкт-Петербург (через секунду)
js

Если бы вместо стрелочной функции мы использовали обычную, this внутри setTimeout указывал бы на window, а не на city. Именно поэтому стрелочные функции так часто используют как колбэки.

Явное управление this

В JavaScript можно явно указать, на что должен указывать this, с помощью трёх методов: call, apply и bind. Это продвинутая тема, но знать о существовании этих методов полезно:

function greet() {
  console.log(`Привет из ${this.name}`);
}

const spb = { name: 'Санкт-Петербург' };
const msk = { name: 'Москва' };

greet.call(spb); // Привет из Санкт-Петербург
greet.call(msk); // Привет из Москва
js

call вызывает функцию немедленно, передавая объект как this. bind возвращает новую функцию с «зафиксированным» this — её можно вызвать позже. Подробнее об этих методах можно почитать в документации MDN.

Главное правило

Чтобы понять чему равен this — смотрите не на то, где написана функция, а на то, как она вызвана:

Способ вызоваЧему равен this
obj.method()obj
function() в строгом режимеundefined
function() без строгого режимаwindow
стрелочная функцияthis из внешнего контекста
fn.call(obj) / fn.apply(obj)obj

this — тема, к которой многие разработчики возвращаются не один раз. Не переживайте, если с первого раза не всё встало на место. Главное — понять, что у this есть логика, и при необходимости всегда можно свериться с doka.guide.

В следующем уроке рассмотрим управляющие конструкции — условия и циклы.