JS: Введение в ООП
Теория: Связывание (bind)
JavaScript — асинхронный язык программирования. Из-за этого функции часто вызываются как колбеки других функций. Особенно много этого в браузере, где колбек на колбеке и колбеком погоняет. Пока мы работали с простыми функциями, это не вызывало никаких затруднений, но все меняется при использовании методов.
На этом этапе мы еще не работали с асинхронностью, но это не должно помешать понять идею. В двух словах: функция setTimeout принимает на вход функцию и время, после которого ее надо вызвать. Когда приходит время, она это делает. В общем-то и всё.
Попробуйте запустить такой код:
Теперь тот же самый код мы хотим вызвать не сразу, а через секунду. Для этого используем функцию setTimeout(), которая вызывает переданную функцию через указанное количество времени.
Этот код выдаст hello, undefined. Почему? Потому что внутрь setTimeout() мы передали не объект printer, а функцию print() без объекта. А значит эта функция потеряла связь с самим объектом и ее this больше не указывает на объект. Вот так можно проиллюстрировать то, что происходит:
Если контекста нет, то this оказывается равным пустому объекту, если мы говорим про обычные функции.
Такое поведение часто нежелательно. Практически всегда, когда передается метод, подразумевается, что он будет вызван в контексте того объекта, которому он принадлежит. Существует несколько способов добиться такого поведения. Самый простой — обернуть функцию в функцию, пока мы вызываем функцию.
Это распространенное решение, которое заодно помогает захватить внешние переменные, когда они нужны для вызова:
Связывание (Bind)
Другой способ — использование метода bind() (переводится как связать). Метод bind() доступен у функций, и в его задачу входит связывание функции с каким-то контекстом. Результатом выполнения bind() будет новая функция, работающая, как и исходная функция, но с привязанным к ней контекстом.
Связанная функция сливается со своим контекстом "намертво". Больше this не поменяется.
Кроме контекста, bind() принимает на вход параметры, которые нужны функции. Причем не сразу все, а любую их часть. bind() подставит их в новую функцию (ту, что вернется из метода bind()) "частично". Эта техника называется "частичное применение функции". Так можно сразу применить нужные аргументы:
Подход с bind() был популярен до появления стрелочных функций, сейчас его используют нечасто. Стрелочные функции проще для понимания и используются повсеместно.
Apply & Call
bind() полезен там, где привязка контекста и вызов функции происходят в разных местах и, как правило, в разное время. Мы встретимся с таким кодом, когда перейдем к асинхронности в JavaScript.
Иногда вызов функций, использующих внутри себя this, происходит сразу вместе с привязкой контекста. Это можно сделать напрямую, сразу же вызвав функцию, возвращаемую bind: ...bind(/* контекст */)():
а можно использовать специально созданные для этого функции apply() и call():
Эти функции внутри себя делают две вещи: меняют контекст и сразу же производят вызов функции. Разница лишь в том, как они работают с аргументами этих функций: apply() – принимает аргументы в виде массива вторым параметром, а call() ждёт на вход позиционные аргументы.
Эти функции позволяют делать довольно необычные вещи, например так:
Вызов выше просто демонстрация, с практической точки зрения он мало полезен. Реальное использование call() и apply() проявляется в связке контекста с функциями из прототипов. Об этом поговорим в следующих уроках.






