Почему нельзя использовать call для передачи контекста в некоторых случаях, а нужно передавать ссылку на функцию?
Что проверяют
Различаете ли вы вызов функции и ссылку на функцию. call не «передаёт контекст», он немедленно выполняет функцию с указанным this и возвращает результат, и половина ошибок с колбэками растёт именно отсюда.
Как отвечать
Скажите прямо: call и apply вызывают сразу, bind создаёт новую функцию и ничего не выполняет. Поэтому там, где нужен колбэк, call неприменим в принципе: подписчиком станет не функция, а то, что она вернула.
btn.addEventListener('click', show.call(user)); // подписали undefined
btn.addEventListener('click', show.bind(user)); // подписали функцию
btn.addEventListener('click', () => show.call(user)); // то же самое явноОбратная ситуация, когда нужна именно ссылка: метод, вытащенный из объекта, теряет this, потому что тот определяется способом вызова. setTimeout(obj.save, 0) вызовет функцию без владельца, и внутри this окажется undefined в строгом режиме. Лечится тем же bind в конструкторе, стрелочным полем класса или обёрткой.
Третий случай: bind каждый раз возвращает новую функцию. Если подписались одной ссылкой, а отписываетесь заново созданной, removeEventListener не сработает и обработчик останется висеть. Ссылку нужно сохранить в переменной или поле.
Где спотыкаются
Пишут fn.call(ctx) прямо в разметке или в addEventListener и удивляются, что обработчик сработал один раз при рендере. Он и не подписывался: функция выполнилась на месте, подписали её результат.
Второе: пытаются задать this стрелочной функции. Своего this у неё нет, она берёт его из места объявления, и call, apply, bind на неё не действуют: переданный объект молча игнорируется.
Третье: считают, что привязку можно переопределить. Повторный bind или call с другим объектом связанную функцию не перепривяжет, первый this остаётся навсегда, и попытка переиспользовать такой обработчик даёт необъяснимое на вид поведение.