Почему нельзя чистить таймер через присвоение переменной таймера значения null?

У меня есть код функции debounce

function debounce(func, time) {
let timer;
    return function () {
        clearTimeout(timer);
        timer = setTimeout(func, time);
    };
}

Почему очищать таймер нужно именно так, а не, допустим, просто присвоением timer значения null?


Ответы (3 шт):

Автор решения: black1277

Очистка таймера с помощью clearTimeout(timer) нужна для того, чтобы отменить уже запланированный вызов переданной функции func, если он существует. Если бы вместо этого вы присваивали timer значение null, это только удалило бы ссылку на текущий таймер, но не остановило бы запланированное выполнение функции func.

Каждый вызов setTimeout возвращает уникальный идентификатор таймера, который используется clearTimeout для определения конкретного таймера, который должен быть отменён. Если новый вызов функции происходит до того, как таймер истёк и функция func была выполнена, clearTimeout гарантирует, что предыдущее выполнение будет отменено, и создастся новый таймер для следующего выполнения func. Это обеспечивает, что функция будет вызвана только один раз, через заданный интервал времени после последнего вызова.

Присвоение timer значения null без предварительной очистки существующего таймера не предотвратит возможного уже запланированного выполнения функции func.

→ Ссылка
Автор решения: Qwertiy
  1. А ты видел, что в переменной? Там число.

    var x = 100
    x = null // Очистили таймер 100?
    
  2. Даже если бы был объект, в js, в отличие от си++, нет определённого времени жизни объектов, а значит, то, что ссылки на некий объект больше не существуют, не означает, что сборщик мусора его скоро соберёт. А даже если соберёт, деструктора всё равно нет (ладно-ладно, теперь через WeakRef можно привязать, но ведь не было же), поэтому код по очистке не выполнить.

  3. Даже если бы это был си++ и уничтожение таймера можно было реализовать через уничтожение ссылки на объект, то вылез бы побочный эффект - ты обязан держать объект до тех пор, пока не выполнится таймер:

    setTimeout(() => {
      // Никогда не произойдёт
      // Поскольку объект не сохранили и он умер сразу же после вызова
      // и отменил таймер
      console.log("Hi")
    }, 100)
    
→ Ссылка
Автор решения: Дмитрий Краснов

Потому что timer, в вашем случае, это не сам таймер, а лишь его идентификатор. Т.е. просто присвоением timer значения null вы потеряете идентификатор вашего таймера и больше не сможете с этим таймером ничего сделать. А сам таймер продолжит работать где-то в браузере.

И даже если бы timer содержал ссылку на сам объект таймера, просто присвоением timer значения null вы потеряли бы эту ссылку. А сам таймер продолжил бы работать где-то в браузере.

→ Ссылка