还有人不知道防抖节流?(一)

·  阅读 95

除夕好!望眉目有山河,清澈明朗。愿心中有丘壑,一往无前。

防抖

事件响应函数在一段时间后才执行,如果在这段时间内再次调用,则重新计算执行时间。当预定的时间内没有再次执行该函数,则执行doSomething。

应用场景

  • scroll事件滚动触发
  • 搜索框输入查询
  • 表单验证
  • 按钮提交事件
  • 浏览器窗口播放,resize事件
function debounce(func, wait, immediate){
    var timeout, result;   
    let decounced = function(){
        // 改变内部this指向
        let context = this;
        // 获取event事件对象,取鼠标事件执行函数参数
        let args = arguments;
        // 每次触发事件执行函数的时候先清空定时器
        clearTimeout(timeout);
        if(immediate){
            let callNow = !timeout; // callNow与定时器相关
            // 延迟事件到了就把定时器清空以便可以重新执行func函数
            timeout = setTimeout(() => {
                timeout = null;
            }, wait);
            //表示立即执行
            if(callNow) result = func.apply(context, args); //执行事件绑定真正执行函数的上下文和参数

        }else {
            //不会立即执行
            timeout = setTimeout(function(){
                result = func.apply(context, args);
            }, wait);
        }
        // 真正执行函数的返回值
        return result;
    }
    // 取消定时器中的事件
    decounced.cancel = function(){
        clearTimeout(timeout);
        timeout = null; // 防止内存泄漏
    }
    return decounced;
}

// 要防抖的函数
function doSomeThing(e){
    console.log(this)   // 绑定事件的对象 btn
    console.log(e)  // event事件对象 点击事件对象
    
  	// 做某些事情...
  
    return '想要的结果';   
}
// 使用
let doSome = debounce(doSomeThing, 5000);
// 绑定点击事件,执行 取消定时器中事件 函数
btn.onclick = function(){
    doSome.cancel();
}
复制代码

节流

如果持续触发事件,每隔一段时间,只会执行一次事件。

应用场景

  • DOM元素拖拽功能的实现
  • 射击游戏
  • 计算鼠标移动的距离
  • 监听scroll滚动事件
function throttle(func, wait, options){
    let context, args, timeout;
    let old = 0;
    if(!options) options = {};
    return function(){
        context = this;
        args = arguments;

        let later = function(){
            old = new Date().valueOf();
            timeout = null;
            func.apply(context, args);
        }

        let now = new Date().valueOf();
        if(options.leading === false && !old){
            old = now;
        }
        if(now - old > wait){
            // 第一次会直接执行
            if(timeout){
                clearTimeout(timeout);
                timeout = null;
            }
            func.apply(context, args);
            old = now;
        }else if(!timeout && options.trailing !== false){
            // 最后一次也会被执行
            timeout = setTimeout(later, wait);
        }
    }
}

function doSomeThing(e){
    console.log(this)   // 绑定事件的对象 btn
    console.log(e)  // event事件对象 点击事件对象
    container.innerHTML = count++;
    return '想要的结果';   
}

let doSome = throttle(doSomeThing, 1000, {
    leading: true,
    trailing: true
})
// 如果想禁用第一次首先执行的话,第三个参数传递, { leading: false },如果想禁用最后一次执行的话,第三个参数传递{ trailing: false }

复制代码
分类:
前端
标签:
分类:
前端
标签: