Что такое bind в JavaScript и как он работает
Что проверяют
Понимаете ли вы, как в JavaScript определяется this и почему метод, переданный как колбэк, теряет свой объект. bind здесь повод поговорить о контексте вызова. Следом обычно просят сравнить его с call и apply, а на сильных позициях написать свою реализацию.
Как отвечать
fn.bind(thisArg, ...args) не вызывает функцию, а возвращает новую, связанную (bound function). У неё зафиксированы this и, если переданы, первые аргументы, то есть bind заодно даёт частичное применение: add.bind(null, 5) возвращает функцию, прибавляющую пять.
Зачем это нужно: this в обычной функции определяется в момент вызова, а не объявления. Передали user.greet в setTimeout или addEventListener, и вызов идёт уже без user, поэтому this становится undefined в строгом режиме (в модулях и классах он включён всегда) или глобальным объектом в нестрогом.
Детали, которые отличают хороший ответ:
- перепривязать нельзя: повторный
bind, а такжеcallиapplyна связанной функцииthisуже не меняют, только добавляют аргументы; newсильнее: при вызове черезnewпривязанныйthisигнорируется и создаётся новый объект;- стрелочные функции: своего
thisу них нет,bindна них меняет только аргументы; - метаданные:
nameстановится"bound greet", аlengthуменьшается на число привязанных аргументов.
Отличие от call и apply: те вызывают функцию сразу, call принимает аргументы списком, apply массивом.
В современном коде bind встречается реже. В React-компонентах на классах методы привязывали в конструкторе, сейчас их заменили стрелочные поля классов и функциональные компоненты.
Где спотыкаются
Снимают обработчик так: removeEventListener("click", this.onClick.bind(this)). Каждый bind создаёт новую функцию, ссылка не совпадает, и обработчик остаётся висеть. Связанную функцию нужно сохранить и снимать именно её.
Вызывают bind прямо в JSX. Каждый рендер даёт новый колбэк, и React.memo у дочернего компонента перестаёт помогать.
В самописной реализации теряют аргументы, переданные при вызове, и забывают про new, ограничиваясь () => fn.apply(ctx, args).