zoukankan      html  css  js  c++  java
  • JS函数的节流和防抖

    防抖(debounce): 触发事件后在n秒内函数只能执行一次,如果在n秒内又触发了事件,则会重新计算函数执行事件

    非立即执行版本:触发事件后函数不会立即执行,而是在n秒后执行,如果在n秒内触发了事件则会重新计算函数执行时间。

    /* 函数防抖 */
    var inputDom = document.querySelectorAll("#debounce")[0];
    /* 非立即执行防抖 */
    var timer = null;
    inputDom.addEventListener("input", function(){
        clearTimeout(timer);
        var self = this;
        var arg = arguments;
        clearTimeout(timer);
        timer = setTimeout(function(){
            //此处不能使用call,应该使用apply,直接将参数放在数组中传
            handle.apply(this, arg);
        }, 800)
    });
    function handle(ev){
        var ev = ev || window.event;
        console.log("ev:", ev);
    }
    
    /* 封装 */
    function debounce(func, wait){
        let timer = null;
        return (function(){
            let self = this;
            let args = arguments;
            if(timer) clearTimeout(timer);
            timer = setTimeout(() => {
                func.apply(self, args)
            }, wait);
        })
    }

    立即执行版本:   触发事件后函数会立即执行,然后n秒内不触发事件才能继续执行函数的效果。

    /* 立即执行防抖 */
    var inputDom = document.querySelectorAll("#debounce")[0];
    var timer;
    inputDom.addEventListener("input", function(){
        if(timer) clearTimeout(timer);
        // 判断是否在等待时间内
        var callNow = !timer;
        timer = setTimeout(() => {
            // 等待一段时间后重置timer
            timer = null
        }, 1000);
        // 如果不在等待时间内,则调用事件处理函数
        if(callNow) handle.apply(this, arguments);
    });
    function handle(ev){
        var ev = ev || window.event;
        console.log("ev:", ev);
    }
    
    /* 封装版本 */
    function debounce(handle, wait){
        let timer;
        return (function(){
            let self = this, args = arguments;
            
            if(timer) clearTimeout(timer);
    
            let callNow = !timer;
            timer = setTimeout(() => {
                timer = null;
            }, 1000);
    
            if(callNow){
                handle.apply(self, args);
            }
        });
    }

    双剑合璧版本:

    /**
     * @desc 函数防抖
     * @param func 函数
     * @param wait 延迟执行毫秒数
     * @param immediate true 表立即执行,false 表非立即执行
     */
    function debounce(func,wait,immediate) {
        let timeout;
    
        return function () {
            let context = this;
            let args = arguments;
    
            if (timeout) clearTimeout(timeout);
            if (immediate) {
                var callNow = !timeout;
                timeout = setTimeout(() => {
                    timeout = null;
                }, wait)
                if (callNow) func.apply(context, args)
            }
            else {
                timeout = setTimeout(function(){
                    func.apply(context, args)
                }, wait);
            }
        }
    }
    

    节流(throttle):指连续触发事件但是在n秒中只执行一次函数。节流会稀释函数的执行频率。

    时间戳版本:

    /* 节流 */
    /* 时间戳版本 */
    var inputDom = document.querySelectorAll("#debounce")[0];
    var previous = 0;
    inputDom.addEventListener("input", function(){
        var now = Date.now();
        if(now - previous > 1000){
            handle.apply(this, arguments);
            // 重置时间戳
            previous = now;
        }
    });
    function handle(ev){
        var ev = ev || window.event;
        console.log("ev:", ev);
    }
    
    /* 封装版本 */
    function throttle(handle, wait){
        let previous = 0;
        return (function(){
            let now = new Date();
            let context = this;
            let args = arguments;
            if(now - previous){
                handle.apply(context, args);
                previous = now;
            }
        })
    }

    定时器版本:

    /* 封装版本 */
    function throttle(handle, wait){
        let timeout;
        return (function(){
            let context = this;
            let args = arguments;
    
            if(!timeout){
                timeout = setTimeout(() => {
                    timer = null;
                    handle.apply(context, args);
                }, wait)
            }
        });
    }

    时间戳版和定时器版的节流函数的区别是:时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候。

    双剑合璧版本:

    /**
     * @desc 函数节流
     * @param func 函数
     * @param wait 延迟执行毫秒数
     * @param type 1 表时间戳版,2 表定时器版
     */
    function throttle(func, wait ,type) {
        if(type===1){
            let previous = 0;
        }else if(type===2){
            let timeout;
        }
        return function() {
            let context = this;
            let args = arguments;
            if(type===1){
                let now = Date.now();
    
                if (now - previous > wait) {
                    func.apply(context, args);
                    previous = now;
                }
            }else if(type===2){
                if (!timeout) {
                    timeout = setTimeout(() => {
                        timeout = null;
                        func.apply(context, args)
                    }, wait)
                }
            }
        }
    }

    参考文献:https://www.jianshu.com/p/c8b86b09daf0

  • 相关阅读:
    Leetcode
    287. Find the Duplicate Number hard
    House Robber III leetcode 动态规划
    将一个数组分成奇数部分和偶数部分,并分别排好序 CVTE
    First Missing Positive && missing number
    permutation II (boss出来了)
    46. Permutations 回溯算法
    字符串分割 函数实现
    Combination Sum II Combinations
    用双缓存技术优化listview异步加载网络图片
  • 原文地址:https://www.cnblogs.com/jett-woo/p/12040419.html
Copyright © 2011-2022 走看看