Как вызывать функцию, в теле которой есть ключевое слово this, в контексте какого-то объекта?
Обычно функции, которые используют ключевое слово this можно встретить при создании класса в JavaScript. Это распространённая практика. При описании класса просто невозможно не использовать this. Классы для того и создают, чтобы из них рождались какие-то объекты.
Но бывают ситуации, когда нужно протестировать какой-то функционал алгоритма и при это не используя обновление свойств класса через свойство prototype. Порой нужно просто написать функцию, которая в своём теле использует ключевое слово this. Такая функция будет доступна на самом верхнем уровне видимости и её имя будет одним из свойств глобального объекта.
Если она будет вызываться вне какого-то конкретного объекта, а сама по себе, то вместо this мы будем получать сам глобальный объект. В случае с клиентскими браузерами это будет объект window, а в случае с серверными приложениями — это будет объект global.
Если внутри тела функции мы обращаемся к таким свойствам this, которых нет у глобального объекта, то мы не получим желаемого результата, а 100% получим ошибку. В этом и кроется проблема. Как исправить эту проблему?
Функции в JavaScript тоже являются объектами, как и всё остальное. Это значит, что объекты функций наследуют от своего прототипа какие-то свойства.
Каждый функциональный объект JavaScript имеет 6 свойств:
- apply(thisArg, argArray)
- bind(thisArg, …args)
- call(thisArg, …args)
- constructor
- toString()
- [@@hasInstance ](V) или литерально «[Symbol.hasInstance]«
Первые три отвечают за привязку объекта контекста для функции.
Метод bind() только привязывает объект контекста для функции, но НЕ вызывает её. По факту он возвращает нам новую функцию с уже привязанным контекстом. Метод bind() принимает первым параметром объект, в контексте которого должна будет в дальнейшем вызываться функция. Мы получаем новый объект функции с правильной привязкой контекста.
Метод call() привязывает объект контекста для функции и СРАЗУ вызывает её.
Метод apply() привязывает объект контекста для функции и СРАЗУ вызывает её. Отличается от call() только формой передачи второго параметра. Метод apply() ждёт «дополнительные параметры» (пробрасываемые) в виде массива.
Зачем нужно привязывать объект контекста вызова функции в JavaScript?
Необходимость привязки объекта контекста вызова функции подробно описана в публикации JavaScript | Что такое this?. Прочитайте её обязательно.
Информационные ссылки
Официальная страница стандарта ECMAScript — https://tc39.es/ecma262/multipage/ — https://tc39.es/ecma262/
Раздел «Properties of the Function Prototype Object» — https://tc39.es/ecma262/#sec-properties-of-the-function-prototype-object