Почему this динамический в JavaScript и когда он определяется
Что проверяют
Понимаете ли вы, что this часть вызова, а не часть функции. Практический смысл прямой: разберётесь ли, почему метод, переданный колбэком, теряет объект, и не начнёте ли лечить это механическим bind во всех местах подряд.
Как отвечать
this вычисляется при входе в функцию, в момент вызова, и зависит от формы этого вызова. Правила по убыванию приоритета:
new Foo(): свежесозданный объект;f.call(obj),f.apply(obj),f.bind(obj): то, что задали явно;obj.method(): объект слева от точки;- просто
f():undefinedв строгом режиме и в модулях, глобальный объект в нестрогом; - стрелочная функция: своего
thisне имеет вовсе, берёт его из лексического окружения, иcallсbindна неё не действуют.
const obj = { n: 1, get() { return this.n; } };
const f = obj.get;
obj.get(); // 1
f(); // в модуле TypeError: this === undefinedДинамика берётся из природы языка: функция это обычное значение, не приколоченное к объекту. Одна и та же функция бывает методом двух объектов сразу, поэтому связать её с получателем можно только в точке вызова.
Где спотыкаются
Отвечают «this это объект, в котором функция объявлена». Место объявления не значит ничего, важен получатель вызова. Проверяется это одной строкой: присвоили метод в переменную, вызвали, контекст исчез.
Теряют контекст при передаче метода: setTimeout(obj.tick, 0), arr.map(this.format), отписка от события ссылкой на другую функцию. Лечится обёрткой-стрелкой, привязкой в конструкторе или полем класса, объявленным стрелкой.
Заучивают, что стрелка «сохраняет this». Она его не сохраняет, а не создаёт, и разница видна на методе объекта: записанный стрелкой, он получит внешний контекст, а не сам объект. Для методов нужна обычная функция.