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

Мы рассмотрим три основных типа функций.

  • Функции метода
  • Функции без методов
  • Стрелочные функции

Мы рассмотрим, как все три из них по-разному обрабатывают контекст.

Контекст функции

Функции могут считаться не имеющими контекста, если они явно не установлены.

Во-первых, мы определим два объекта и функцию, которая будет воздействовать на них:

Функция Function.apply() позволяет вам установить контекст функции так, как вы ее вызываете, обрабатывая контекст как любой другой параметр.

Function.bind() создаст прокси-функцию. Этот прокси при вызове вызовет исходную функцию с указанным контекстом.

Контекст функции также изменится, если она вызывается как метод объекта. Обратите внимание, что по-прежнему существует только одна функция, просто на нее ссылаются по-разному. То, как ссылаются на функцию, влияет на ее контекст.

Дополнительная информация о контексте функции

В зависимости от среды выполнения JavaScript и если установлено «use strict», вызов get_color() без контекста может не привести к ошибке времени выполнения. В браузерах без «use strict» объект окна используется как контекст по умолчанию для функций. Если установлено «use strict» или если вы находитесь в другой среде выполнения, у функции не будет контекста, и «this» будет неопределенным.

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

Еще одна вещь — Function.apply() бесполезна для функций, сгенерированных с помощью Function.bind(). Это изменит контекст прокси-функции, но прокси не устанавливает контекст на основе своего собственного контекста. Поэтому, хотя это не выдаст вам ошибку, оно не будет работать должным образом.

Подробнее о методах

Контекст метода — это его объект-контейнер. Как правило, это верно независимо от того, как создается объект или как метод был прикреплен к этому объекту.

Давайте определим объект и назначим ему два метода двумя разными способами.

Посмотрите, как обе функции правильно захватывают контекст объекта, несмотря на то, что одна из них сначала объявлена ​​как функция, не являющаяся методом.

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

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

Стрелочные функции просты, у них нет контекста. Однако они будут захватывать переменную this так же, как и любую другую переменную. Поскольку у них нет контекста, Function.apply() и Function.bind() не влияют на функции стрелок.

Собираем все вместе

Отслеживайте, как контекст меняется по мере выполнения скрипта:

Заключение

  • Функции имеют контекст, на который можно ссылаться через переменную this.
  • Контекст можно указать вручную с помощью apply() и bind() или привязать, установив функцию как метод.
  • Контекст метода — это его объект-контейнер.
  • Стрелочные функции не имеют контекста, но могут захватывать переменную this.