Что такое this в JavaScript

Выясним, что это за ключевое слово this в методах объекта, зачем оно нужно, и как его правильно использовать.

JavaScript language

Вопрос про ключевое слово this очень популярен на собеседованиях, а само оно часто используется на практике. Поэтому мы решили разобраться в этой проблеме и рассказать всё, что вам необходимо знать об этом явлении.

Объекты и this

Начнём сразу с того, что область применения this в основном относится к ОПП (объектно-ориентированному программированию). Если вы видите структуру кода, построенную по принципу ОПП, то значит ключевое слово this там активно используется.

Давайте создадим простой объект:

let instance = {
  user: "John"
};

И, допустим, нам нужно создать метод, который бы менял имя пользователя:

let instance = {
  user: "John",
  changeUser(newVal) {
    instance.user = newVal;
  }
};

instance.changeUser("Paul");
console.log(instance.user); // "Paul"

Свойство объекта, в котором содержится функция, называется методом и может иметь сокращённую запись: changeUser() {} вместо changeUser: function() {}.

В этом примере мы получили доступ к свойству user через ссылку на объект instance. Но является ли такой способ надёжным? Совершенно точно нет. Просто представьте такую ситуацию, где нам нужно скопировать объект с указанным в нём методом:

let instance = {
  user: "John",
  changeUser(newVal) {
    instance.user = newVal;
  }
};

let copy = instance;
instance = null;

copy.changeUser("Paul");
console.log(copy.user); // Ошибка

Видим ошибку, так как метод пытается получить доступ к уже несуществующему свойству из оригинального объекта. Как сделать метод более универсальным? Ответ очень прост: использовать ключевое слово this.

let instance = {
  user: "John",
  changeUser(newVal) {
    this.user = newVal;
  }
};

let copy = instance;
instance = null;

copy.changeUser("Paul");
console.log(copy.user); // "Paul"

Теперь всё работает как надо.

Подытожим: когда функция вызывается как метод объекта, используемое в этой функции ключевое слово this принимает значение объекта, по отношению к которому вызван метод.

Разный контекст

В отличии от большинства других языков программирования, ключевое слово this не является фиксированным. Поэтому оно вычисляется уже по ходу и зависит от контекста, в котором используется. Выше мы рассмотрели this в контексте метода объекта, рассмотрим и некоторые другие случаи.

Global

Попробуйте обратиться к this вне любой функции и вы получите ссылку на глобальный объект window:

console.log(this); // window
console.log(window); // тот же объект

Function

В простом вызове ключевое слово this вернёт глобальный объект, как и в предыдущем случае:

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

myFun(); // window

Если нужно использовать в качестве this определённый объект, то вызовите функцию при помощи call или apply:

function myFun() {
  console.log(typeof(this));
};

myFun.call(2); // Object

Обратите внимание, что при попытке использования примитивов в качестве значения, это значение будет преобразовано в объект при помощи ToObject. Таким образом, число в примере стало объектом.

Ещё есть метод bind, который клонирует исходную функцию, но в качестве this использует объект указанный в первом аргументе:

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

myFun(); // window

const myBind = myFun.bind({ a: 1 });

myBind(); // Object { a: 1 } 

Стрелочная функция

Рассмотрим следующий пример:

const instance = {
  user: "John",
  showName() {
    function fun() {
      console.log(this);
    }
    fun();
  }
};

instance.showName(); // ??

Чем будет являться this? Объектом instance? А вот и нет, this в данном случае будет ссылаться на глобальный объект window. Так происходит потому, что функция fun() не является методом, соответственно this в ней используется в контексте функции и возвращает глобальный объект.

Переделаем пример, но уже с использованием стрелочной функции:

const instance = {
  user: "John",
  showName() {
    const fun = () => {
      console.log(this);
    };
    fun();
  }
};

instance.showName(); // Object instance

Теперь this ссылается на созданный объект.

Это одна из ключевых особенностей стрелочной функции. Она не вычисляет свой собственный this, а берёт его значение из внешней классической функции. Запомните этот случай, вы встретите его ещё не один раз.

Event Listener

При использовании классической функции как обработчика, this будет ссылаться на прослушиваемый элемент DOM.

function handler() {
  console.log(this); // <div></div>
};

document.querySelector("div").addEventListener("click", handler); 

Если использовать стрелочную функцию, то вы получите значение из внешней функции либо глобальный объект:

const handler = () => {
  console.log(this); // window
};

document.querySelector("div").addEventListener("click", handler);

Ключевое слово this в инлайновом обработчике будет ссылаться на DOM элемент, в котором он расположен.

Итог

В этом тексте мы постарались рассказать вам максимально просто и понятно про ключевое слово this. Также рекомендуем прочитать статьи по этой теме на javascript.ru и MDN web docs.

Подписывайтесь и читайте новые фронтенд-материалы от Frontext.

Наши рекомендации
К сожалению, тут пока ничего нет.