Как сделать функцию вызываемой через точку в JavaScript
Что проверяют
Понимаете ли вы, что метод в JavaScript это просто функция в свойстве объекта, и как при вызове через точку определяется this. Следом спрашивают, что будет, если метод достать в переменную или передать колбэком.
Как отвечать
Формулировка допускает несколько трактовок, уточните, какую имеют в виду. Каркас такой:
- метод объекта:
const user = { name: "Ann", greet() { return this.name; } }. При вызовеuser.greet()вthisпопадает объект слева от точки; - метод класса: объявленный в теле
class, он живёт вprototypeи общий для всех экземпляров; - свойство самой функции: функция тоже объект, поэтому
debounce.cancel = () => {}работает. Так устроены многие библиотеки, гдеlib()иlib.method()соседствуют; - цепочка вызовов: чтобы писать
calc.add(2).mul(3), каждый метод возвращаетthisили новый объект; prototypeвстроенных типов:Array.prototype.last = ...технически сработает, но трогать чужие прототипы не стоит, об этом ниже.
Ключевое: this определяется в момент вызова, а не в момент объявления. const fn = user.greet; fn() потеряет контекст, в строгом режиме и в модулях this будет undefined. Контекст закрепляют через bind, стрелочную обёртку () => user.greet() или поле класса со стрелкой.
Стрелочная функция своего this не имеет и берёт его из внешней области, поэтому как метод объектного литерала она не подходит, а как колбэк внутри метода, наоборот, удобна.
Где спотыкаются
Объявляют метод стрелкой прямо в литерале объекта и получают this, указывающий не на объект.
Передают метод в addEventListener или setTimeout без bind и получают в this DOM-элемент или window вместо своего объекта.
Расширяют Array.prototype или String.prototype. Это ломает перебор через for...in, конфликтует с другими библиотеками и с будущими методами стандарта: именно из-за такого конфликта в языке появились flat и includes вместо задуманных flatten и contains.