Sky
HOME
HOME
  • 前端笔记

    • CSS

      • 盒子模型
      • 屏幕单位
      • CSS 性能优化
    • JavaScript

      • Methods

        • Scheduler
        • Deep Clone
        • Curry
        • Calculation Function
        • debounce & throttle
      • Function bind
      • Array reduce
      • cross domain
      • event loop
      • ajax
      • event
      • context
      • inheritance
      • prototype
    • HTML

      • html render
      • forbidden <a>
      • <meta>
      • <script>
    • uni-app

      • scroll table

debounce & throttle | 防抖 & 节流

防抖 -> 定时器外重置&清除定时器 节流 -> 定时器内重置&清除定时器

debounce | 防抖

防抖:在事件被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时。


/**
** 防抖函数,返回函数连续调用时,空闲时间必须大于或等于 wait,func 才会执行
** @param  {function} func        回调函数
** @param  {number}   wait        需要等待的时间,单位毫秒
** @param  {boolean}  immediate   设置为true时,是否立即调用函数
** @return {function}             返回客户调用函数
**/

function debounce(func, wait = 50, immediate = true) {
    let timer, context, args;

    // 延迟执行函数
    const later = () => setTimeout(() => {
        // 延迟函数执行完毕,清空缓存的定时器序号
        timer = null;
        // 延迟执行的情况下,函数会在延迟函数中执行
        // 使用到之前缓存的参数和上下文
        if (!immediate) {
            func.apply(context, args);
            context = args = null;
        }
    }, wait);

    // 这里返回的函数是每次实际调用的函数
    return function(...params) {
        // 如果没有创建延迟执行函数(later),就创建一个
        if (!timer) {
            timer = later();
            // 如果是立即执行,调用函数
            // 否则缓存参数和调用上下文
            if (immediate) {
                func.apply(this, params);
            } else {
                context = this;
                args = params;
            }
        // 如果已有延迟执行函数(later),调用的时候清除原来的并重新设定一个
        // 这样做延迟函数会重新计时
        } else {
            clearTimeout(timer);
            timer = later();
        }
    };
}

throttle | 节流

节流:规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。


/**
 * 节流函数 (第一次和最后一次都会执行)
 * @param {function} func 回调函数
 * @param {number} delay 延迟时间
 * @returns {function} 返回客户调用函数
 * 
 * */ 

    function throttle(func, delay) {
        let start = 0, timer=null;
        return function (...args) {
            let now = Date.now();
            if (now - start < delay) {
                if (timer) clearTimeout(timer);
                timer = setTimeout(() => { // 保证在当前时间区间结束后,再执行一次func
                    start = now;
                    func.apply(this, args);
                }, delay);
            } else {
                start = now;
                func.apply(this, args);
            }
        }
    }
    
最近更新: 2023/12/1 17:48
Contributors: liujw155@outlook.com
Prev
Calculation Function