美文网首页
JavaScript基础(四)防抖

JavaScript基础(四)防抖

作者: 前端开发爱好者 | 来源:发表于2019-03-15 00:35 被阅读0次

    需求

    在日常的前端开发中,一般会遇到一些会被频繁触发的事件,比如:window.resize,window.scroll,mousedown,mousemovekeydown,keyup,或者输入框等。这些函数或者是事件一般会被非常频繁的触发。

    方案

    为了解决这个问题一般会有两种解决方案:防抖(debounce)和节流(throttle)

    防抖

    原理:假定时间间隔是n秒。那么就是在函数第一次被调用时延时n秒后执行。在这n秒期间之内,再次触发,则以新的事件为准

    第一版实现

    function deBounce(func, wait) {
        var timeFlag;
        return function () {
            clearInterval(timeFlag);
            timeFlag = setTimeout(func, wait)
        }
    }
    
    

    第二版实现

    第一版实现中会存在this指向不正确的问题

    
    function deBounce(func, wait) {
        var timeFlag;
        return function () {
            var context = this;
            clearInterval(timeFlag);
            timeFlag = setTimeout(function () {
                func.apply(context)
            }, wait)
        }
    }
    
    或者使用bind
    function deBounce(func, wait) {
        var timeFlag;
        return function () {
            clearInterval(timeFlag);
            timeFlag = setTimeout(func.bind(this), wait)
        }
    }
    

    第三版实现

    第二版中的实现存在传参的问题

    function deBounce(func, wait) {
        var timeFlag;
        return function () {
            var context = this;
            var args = arguments
            clearInterval(timeFlag);
            timeFlag = setTimeout(function () {
                func.apply(context, args)
            }, wait)
        }
    }
    
    或者bind
    
    function deBounce(func, wait) {
        var timeFlag;
        return function (...args) {
            clearInterval(timeFlag);
            timeFlag = setTimeout(func.bind(this, ...args), wait)
        }
    }
    
    或者es6
    const deBounce = (func, wait) => {
        let timeFlag;
        return function (...args) {
            clearInterval(timeFlag);
            timeFlag = setTimeout(func.bind(this, ...args), wait)
        }
    };
    

    第四版实现

    有时会有需要立即执行的需求。

    function deBounce(func, wait, immediate) {
        var timeFlag;
        return function () {
            var context = this;
            var args = arguments;
            timeFlag && clearInterval(timeFlag);
            if (immediate) {
                var callNow = !timeFlag;
                timeFlag = setTimeout(function () {
                    timeFlag = null
                }, wait);
                if (callNow) func.apply(context, args)
            } else {
                timeFlag = setTimeout(function () {
                    func.apply(context, args)
                }, wait)
    
            }
        }
    }
    // 或者
    
    const deBounce = (func, wait, immediate) => {
        let timeFlag;
        return function (...args) {
            clearInterval(timeFlag);
            if (immediate) {
                const oldFlag = !timeFlag;
                timeFlag = setTimeout(() => {
                    timeFlag = null
                }, wait);
                oldFlag && func.apply(this, args)
            } else {
                timeFlag = setTimeout(func.bind(this, ...args), wait)
            }
        }
    };
    

    第五版

    第四版的函数仍然存在部分问题。就是当函数立即执行时。可能需要函数的返回值,所以修改后有下面第五版

    function deBounce(func, wait, immediate) {
        var timeFlag;
        var deBounced = function () {
            var context = this;
            var args = arguments;
            var result;
            timeFlag && clearInterval(timeFlag);
            if (immediate) {
                var callNow = !timeFlag;
                timeFlag = setTimeout(function () {
                    timeFlag = null
                }, wait);
                if (callNow) result = func.apply(context, args)
            } else {
                timeFlag = setTimeout(function () {
                    func.apply(context, args)
                }, wait)
    
            }
            return result
        };
        deBounced.cancel = function () {
            clearTimeout(timeout);
            timeout = null;
        };
        return deBounced;
    }
    
    // es6
    const deBounce = (func, wait, immediate) => {
        let timeFlag;
        const deBounced = (...args) => {
            clearInterval(timeFlag);
            if (immediate) {
                const oldFlag = !timeFlag;
                timeFlag = setTimeout(() => {
                    timeFlag = null
                }, wait);
                oldFlag && func.apply(this, args)
            } else {
                timeFlag = setTimeout(func.bind(this, ...args), wait)
            }
        };
        deBounced.cancel = () => {
            clearTimeout(timeFlag);
            timeFlag = null;
        };
        return deBounced
    };
    

    相关文章

      网友评论

          本文标题:JavaScript基础(四)防抖

          本文链接:https://www.haomeiwen.com/subject/qelkmqtx.html