Ключевое слово this
Free PreviewЕсли замыкания — одна из частых тем для обсуждения в 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.
В следующем уроке рассмотрим управляющие конструкции — условия и циклы.