Куда указывает this в обычном JavaScript скрипте
Что проверяют
Знаете ли вы, что this определяется способом вызова, а не местом объявления функции, и помните ли разницу между обычным скриптом, модулем и строгим режимом. Следом почти всегда показывают код с методом, переданным в setTimeout или в обработчик, и спрашивают, что выведется.
Как отвечать
Сначала прямой ответ на вопрос:
- верхний уровень классического скрипта:
thisэто глобальный объект, в браузереwindow, то же, чтоglobalThis. Строгий режим на это не влияет; <script type="module">: на верхнем уровнеthisравенundefined, модули всегда строгие;- Node.js: в CommonJS-модуле наверху
thisэтоmodule.exports, в ES-модулеundefined.
Потом правила для функций, по убыванию приоритета:
new:thisэто новый объект;call,apply,bind:thisзадан явно, повторныйbindуже ничего не меняет;- вызов через точку:
obj.method()получаетobj; - простой вызов
f(): в нестрогом режиме глобальный объект, в строгомundefined. Тела классов строгие автоматически; - стрелочная функция: своего
thisнет, он берётся из окружающей области, иcallего не поменяет.
Для фронтенда добавьте обработчики: обычная функция в addEventListener получает элемент, на котором висит обработчик (event.currentTarget), стрелочная нет. В классовых React-компонентах методы привязывали через bind в конструкторе или стрелочные поля класса, в функциональных компонентах вопрос исчез.
Где спотыкаются
Отрывают метод от объекта: const f = obj.method; f(). В строгом режиме this будет undefined, и обращение к свойству бросит TypeError. А setTimeout(obj.method) в браузере вызовет метод с window, и тот молча прочитает не те данные.
Пишут метод объекта стрелкой и ждут, что this будет объектом. На верхнем уровне скрипта this.name внутри такой стрелки вернёт window.name, то есть пустую строку, а не undefined, что путает ещё больше.
Считают, что в модуле this наверху тоже window, и переносят старый код из обычного скрипта в модуль без проверки.