Throttle для скролла
throttleограничивает частоту вызова функции — не чаще одного раза в N миллисекунд — идеально для событий scroll и resize.
Задача
Событие scroll может срабатывать десятки раз в секунду. Тяжёлый обработчик (вычисления позиций, DOM-манипуляции) должен вызываться не чаще, чем нужно — раз в 16 мс (60 fps) или реже.
Решение
Реализация throttle:
function throttle(fn, limit) {
let lastCall = 0;
return function (...args) {
const now = Date.now();
if (now - lastCall >= limit) {
lastCall = now;
fn.apply(this, args);
}
};
}
Применение к событию scroll:
function onScroll() {
const scrollY = window.scrollY;
// Показать кнопку "наверх" при прокрутке > 300px
const btn = document.getElementById('backToTop');
btn.hidden = scrollY < 300;
// Показать прогресс-бар чтения
const progress = document.getElementById('readProgress');
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
progress.style.width = `${(scrollY / docHeight) * 100}%`;
}
window.addEventListener('scroll', throttle(onScroll, 100), { passive: true });
requestAnimationFrame-вариант — для анимационной синхронизации:
function throttleRAF(fn) {
let rafId = null;
return function (...args) {
if (rafId) return;
rafId = requestAnimationFrame(() => {
fn.apply(this, args);
rafId = null;
});
};
}
window.addEventListener('scroll', throttleRAF(onScroll), { passive: true });
Ключевые моменты
{ passive: true }вaddEventListener— браузер знает, что обработчик не вызоветpreventDefault, и не блокирует скролл; критично для производительности.throttlevsdebounce: throttle вызывает регулярно (раз в N мс), debounce ждёт паузы. Для scroll — throttle; для input поиска — debounce.requestAnimationFrame-вариант привязывает вызов к кадрам рендера (~16 мс), что оптимально для визуальных изменений.Date.now()точнееnew Dateи не создаёт объект — предпочтительно в горячем пути.
Варианты
IntersectionObserver— для отслеживания видимости элементов при скролле безscrollсобытия вообще (более эффективно).- Lodash
_.throttle(fn, 100)— с опциямиleading/trailingдля точного управления.