Для простоты я буду называть значение 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.