Как работает this внутри функции-конструктора и при обычном вызове функции в JavaScript
Что проверяют
Понимаете ли вы, что значение this в JavaScript определяется не местом объявления функции, а способом её вызова, и умеете ли перечислить все способы привязки.
Как отвечать
- Вызов через
new: создаётся пустой объект, его прототипом становитсяCtor.prototype, this внутри указывает на этот объект, и он же возвращается неявно. Если конструктор явно вернёт объект, вернётся он; примитив вreturnигнорируется. - Обычный вызов
f(): this равенundefinedв строгом режиме, а строгий режим включён во всех ES-модулях и телах классов, то есть практически во всём современном коде. В нестрогом режиме this подменяется глобальным объектом. - Вызов методом
obj.f(): this равен объекту слева от точки и вычисляется в момент вызова. Стоит передать метод по ссылке (вsetTimeout, в обработчик события), и контекст теряется. call,apply,bindзадают this явно;bindсоздаёт новую функцию с жёсткой привязкой, повторныйbindеё не переопределяет.- Стрелочная функция своего this не имеет, берёт его лексически из места объявления, поэтому её нельзя вызвать через
newи бессмысленно биндить.
function Person(name) {
if (!new.target) throw new Error("нужен new");
this.name = name;
}
const p = new Person("Аня");
const hi = { name: "Аня", hi() { return this.name } }.hi;
hi(); // undefined: контекст потерян
hi.call({ name: "Боб" }); // "Боб"Где спотыкаются
Говорят, что при обычном вызове this всегда window. В модулях и в строгом режиме это undefined, а именно так исполняется код, собранный любым современным сборщиком.
Считают, что метод «помнит» свой объект. Он не помнит: привязка происходит на каждом вызове, поэтому const g = obj.method; g() ломается, а obj.method() работает.
Не могут объяснить, почему стрелка в поле класса решает проблему обработчика события, а обычный метод нет, и не видят разницы с bind в конструкторе: поле создаётся заново на каждый экземпляр.
Ограничиваются фразой «new создаёт объект», забывая про установку прототипа, неявный возврат и правило про объект в return.