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

1. Контекст исполнения (this)

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

Контекст в JavaScript похож на контекст в предложении:

  • Петя бежит быстро, потому что Петя пытается поймать поезд.

  • Петя бежит быстро, потому что он пытается поймать поезд.

Второе предложение звучит лаконичнее. Предметом предложения является Петя и мы можем сказать, что контекст предложения — это Петя, потому что он в центре внимания в это конкретное время в предложении. Даже местоимение кто относится к Пете.

И точно так же объект может быть текущим контекстом исполнения функции.

// Петя бежит быстро, потому что Петя пытается поймать поезд.
const petya = {
  name: 'Petya',
  showName() {
    console.log(petya.name);
  },
};

petya.showName();
Copy

Обращение к свойствам объекта внутри методов, используя имя самого объекта, аналогично использованию Петя вместо он.

У всех функций есть локальная переменная this. Во время исполнения функции в переменную this записывается ссылка на объект в контексте которого она вызывается.

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

2. Правила определения this

Необходимо усвоить всего одно правило для определения this.

2.1. this в глобальной области видимости

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

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

Если функция была вызвана как метод объекта, то контекст будет ссылаться на объект, частью которого является метод.

Более сложный пример для лучшего понимания:

  • Сначала создадим функцию в глобальной области видимости и вызовем ее.

  • После чего присвоим ее в свойство объекта и вызовем как метод этого объекта.

2.3. this в функциях обратного вызова

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

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

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

Стрелочные функции также игнорируют наличие строгого режима. Если стрелка запомнила глобальный контекст, то this в ней будет содержать ссылку на window вне зависимости выполняется ли скрипт в строгом режиме или нет.

Ограничивая стрелочные функции постоянным контекстом, JavaScript-движки могут лучше их оптимизировать, в отличие от обычных функций, значение this которых может быть изменено.

Пример не практичный, но отлично показывает как работает контекст для стрелок. Значение контекста берется из родительской области видимости.

Если привести этот код к ES5, получится следующее.

3. Методы функций call, apply, bind

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

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

Функция - это на самом деле довольно хитрый объект, поэтому у нее тоже есть методы. С помощью методов call и apply можно выполнить функцию в контексте какого-то объекта, не делая функцию его методом.

3.1. call и аргументы

Запомнить правило использования call довольно легко: метод call вызовет функцию fn передав ее this ссылку на объект obj, а также аргументы arg1, arg2 и т. д.

3.2. apply и аргументы

Метод apply - полный аналог метода call за исключением того, что синтаксис вызова аргументов требует не перечисление, а массив.

3.3. bind

Мы рассмотрели случаи, когда необходимо мгновенно вызвать функцию с другим контекстом - для этого используются методы call и apply. Но в случае функции обратного вызова, когда необходимо не вызвать функцию на месте, а передать ссылку на эту функцию, причем с привязанным контекстом, call и apply не подходят. Метод bind позволяет решить эту задачу.

Метод bind создает копию функции fn с привязанным контекстом obj и аргументами arg1, arg2 и так дале, после чего возвращает ее как результат своей работы. В результате мы получаем копию функции с привязанным контекстом, которую можно передать куда угодно и вызвать когда угодно.

Чаще всего метод bind используется для привязки контекста при передаче методов объекта как функций обратного вызова. Возьмем проблемный пример из предыдущей секции. Задачу привязки контекста мы теперь можем решить используя метод bind, передав функцией обратного вызова копию метода с привязанным контекстом.

Last updated