Как отсутствие собственного this у стрелочной функции влияет на вызов методов в JavaScript?
Что проверяют
Можете ли вы предсказать значение this по коду: у обычной функции оно определяется в момент вызова, у стрелочной берётся из места, где функция создана. Следом обычно дают фрагмент со стрелкой в литерале объекта и спрашивают, что он выведет и поможет ли bind.
Как отвечать
- обычная функция:
thisзависит от формы вызова.obj.method()даётobj, вызов без объекта даётundefinedв строгом режиме (модули и классы строгие всегда) или глобальный объект в нестрогом,newсоздаёт новый объект,call,applyиbindзадают значение явно; - стрелочная функция: своего
thisнет, как нетarguments,superиnew.target. Значение берётся лексически из окружающей области.call,applyиbindего не меняют, аnewна стрелке бросаетTypeError; - стрелка как метод объекта: в
const obj = { v: 42, get: () => this.v }литерал объекта не создаёт своей области дляthis. В ES-модуле на верхнем уровнеthisравенundefined, и вызовobj.get()упадёт сTypeError. В обычном скрипте браузераthisокажетсяwindow, и результат будетundefined; - где стрелка полезна: колбэки внутри метода (
forEach,setTimeout,then) видятthisсамого метода, безconst self = thisиbind; - поля класса:
handleClick = () => { ... }привязано к экземпляру, его можно передать как обработчик без потери контекста. Цена: функция создаётся для каждого экземпляра, лежит не в прототипе, и наследник не вызовет её черезsuper.handleClick().
Классическая потеря контекста у обычного метода выглядит так: const f = obj.method; f() или button.addEventListener("click", obj.method). В первом случае this будет undefined (в строгом режиме), во втором это сам элемент.
Где спотыкаются
Объявляют методы объекта стрелками, ожидая, что this будет объектом. Ошибка всплывает не сразу, а при первом обращении к свойству.
Пытаются починить стрелку через bind(obj). Вызов молча вернёт функцию с тем же this.
Путают лексическое связывание с динамическим и думают, что стрелка берёт this у того, кто её вызвал. В обработчике события стрелка не даст элемент в this, для этого есть event.currentTarget.