Что выведет этот фрагмент на привязку this и почему?
Что выведет следующий код и почему? (Нестрогий режим, браузер, name глобально не задан.)
const obj = {
name: 'obj',
method() { console.log(this.name); },
arrow: () => console.log(this.name),
};
obj.method();
const fn = obj.method;
fn();
obj.arrow();
setTimeout(obj.method, 0);
Предскажите вывод и объясните.
Печатает obj, затем '' три раза. this задаётся местом вызова, а не местом определения функции. obj.method() привязывает this к obj. Оторванный fn() и колбэк setTimeout — обычные вызовы, поэтому this — глобальный объект (window.name это ''). У стрелки нет своего this; она наследует внешний this модуля, тоже давая ''.
- ✗Думать, что
thisфиксируется при определении, а не задаётся местом вызова - ✗Считать, что стрелка внутри литерала объекта привязывает
thisк этому объекту - ✗Ожидать, что оторванный метод сохраняет исходного получателя
- →Как оторванный
fn()повёл бы себя иначе в строгом режиме? - →Как передача
obj.method.bind(obj)вsetTimeoutизменит вывод?
Решение
this определяется тем, КАК вызвана функция, а не где она объявлена; у стрелки своего this нет.
obj.method(); // 'obj' — вызвана как метод obj
const fn = obj.method;
fn(); // '' — обычный вызов, this = глобальный объект
obj.arrow(); // '' — стрелка наследует внешний this
setTimeout(obj.method, 0); // '' — колбэк вызван без получателя
Как это работает
obj.method() вызывается с получателем obj, поэтому this.name это 'obj'.
const fn = obj.method; fn() — это обычный вызов без получателя. В нестрогом режиме this откатывается к глобальному объекту (window), а window.name — это ''. То же самое с setTimeout(obj.method, 0): таймер вызывает функцию без obj слева, поэтому получателя нет.
obj.arrow — стрелочная функция; у неё нет собственного this, она берёт его из внешней области, где определён литерал (модуль/верхний уровень), что тоже даёт ''. Привязка стрелки не зависит от того, что она записана внутри объекта.