前端优化中的防抖与截流

Posted aiguangyuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端优化中的防抖与截流相关的知识,希望对你有一定的参考价值。

1. 什么是防抖?

在事件触发后的指定时间之后,再去执行真正需要执行的函数,如果在该时间之内事件又被触发,则重新开始计时。

常见的应用场景:

1. 滚动事件触发;

2. 搜索框输入查询;

3. 表单验证;

4. 按钮提交事件;

5. 浏览器窗口缩放;

以下是代码实现:

function debounce(func, time, immediate) 
    // 用来获取返回值
    let timer, result;

    let debounced = function () 
        // 保存当前指向
        let that = this;
        // 获取函数的参数
        let args = arguments;
        // 清除当前定时器
        clearTimeout(timer);
        // 立即执行
        if (immediate)  
            let callNow = !timer;
            // 指定时间内不再执行
            timer = setTimeout(function () 
                timer = null;
            , time);

            if (callNow)
                result = func.call(that, ...args);
            ;

        // 不立即执行
         else  
            // 指定时间后触发函数
            timer = setTimeout(function () 
                // 改变函数内部指向,并传递参数
                func.call(that, ...args);

            , time);
        ;
        return result;
    ;

    // 取消函数
    debounced.cancel = function () 
        // 清除定时器
        clearTimeout(timer); 
        // 定时器置空
        timer = null; 
    ;
    // 返回防抖函数
    return debounced; 

2. 什么是截流?

在指定时间内触发多次函数的话,只有一次是可被执行的,下一次执行只能等到下一个周期里。

常见的应用场景:

1. DOM元素的拖拽功能实现;

2. 射击游戏;

3. 计算鼠标的移动距离;

4. 监听滚动事件;

截流函数根据是否立即执行,操作完成后是否还会执行一次,分为三种情况:

1. 用时间戳来实现。第一次立即执行,操作完成后不再执行;

function throttle(func, time) 
    let that, args;
    let old = 0;
    return function () 
        // 获取当前的时间戳
        let now = new Date().valueOf(); 
        // 保存当前指向
        that = this; 
        // 获取函数的参数
        args = arguments; 
        if (now - old > time) 
            // 改变函数内部指向,并传递参数
            func.apply(that, args); 
            // 更新旧时间戳
            old = now; 
        
    
;

2. 用定时器实现节流函数。第一次延时执行,操作完成后还会执行一次;

function throttle(func, time) 
    let that, args, timer;
    return function () 
        // 保存当前指向
        that = this;
        // 获取函数的参数
        args = arguments;
        if (!timer) 
            timer = setTimeout(function () 
                timer = null;
                func.apply(that, args);
            , time);
        
    
;

3. 用时间戳与定时器结合实现截流函数。第一次立即执行,操作完成后还会执行一次;

function throttle(func, time) 
    let that, args, timer;
    let old = 0; 

    return function () 

        // 保存指向
        that = this;
        args = arguments;

        let now = new Date().valueOf(); 
        if (now - old > time) 
            if (timer) 
                clearTimeout(timer);
                timer = null;
            
            func.apply(that, args);
            old = now;
        ;

        if (!timer) 
            timer = setTimeout(function () 
                // 更新最新的时间戳
                old = new Date().valueOf(); 
                timer = null;
                func.apply(that,args);
            , time);
        
    

最终版,用时间戳与定时器结合实现截流函数。根据参数来决定开始是否立即执行,结束后是否还会执行。

function throttle(func, time, options)  
    let that, args, timer;
    // 设置初始时间戳
    let old = 0; 
    // 如果没有该参数,置为空对象
    if(!options)options = ; 

    return function () 
        that = this;
        args = arguments;

        // 获取初始的时间戳
        let now = new Date().valueOf(); 

        // leading为false表示不立即执行
        if (options.leading === false && !old) 
            old = now; 
        ;

        if (now - old > time)  
            if (timer) 
                clearTimeout(timer);
                timer = null;
            
            func.apply(that, args);
            old = now;
        ;

        // trailing为true表示最后一次会被执行
        if (!timer && options.trailing==true)  
            timer = setTimeout(function () 
                // 更新最新的时间戳
                old = new Date().valueOf(); 
                timer = null;
                func.apply(that,args);
            , time);
        
    

以上是关于前端优化中的防抖与截流的主要内容,如果未能解决你的问题,请参考以下文章

javascript中的防抖与节流。

Js中的防抖与节流

vue正确的使用函数的防抖与节流

防抖与节流

JS的防抖与节流 -- springboot实战电商项目mall4j

lodash的防抖和节流方法