Выбор ответа Middle Реализация с нуля обновлено

debounce со стрелкой вместо function

Вопрос

Эту реализацию используют как метод: form.save = debounce(function () { this.submit(); }, 300). Что пойдёт не так при вызове form.save()?

function debounce(fn, ms) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), ms);
  };
}

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: this в fn будет из вызова debounce (в модуле undefined), и submit упадёт. Возвращаемая обёртка стрелочная, поэтому её this берётся из места создания, то есть из вызова debounce(...), а не из form.save().

Варианты ответа

  1. Ничего: стрелки берут this объекта, на котором вызваны, и this будет form
  2. Функция вызовется сразу, без задержки, потому что стрелка не ждёт setTimeout
  3. this в fn будет из вызова debounce (в модуле undefined), и submit упадётправильный ответ
  4. Таймер не сбросится между вызовами, и fn вызовется на каждый вызов save()

Разбор

Возвращаемая обёртка стрелочная, поэтому её this берётся из места создания, то есть из вызова debounce(...), а не из form.save(). В модуле или строгом режиме это undefined, и fn.apply(this, ...) передаст undefined. Нужно возвращать обычную function (...args), тогда this будет объектом, на котором вызвали метод. Внутренняя стрелка в setTimeout как раз правильна: она берёт this обёртки. Задержка и сброс таймера здесь работают корректно.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.