JS函数节流防抖

作者: bestvist | 来源:发表于2017-10-18 00:35 被阅读125次

    在前端开发中有一部分的用户行为会频繁的触发事件执行,而对于DOM操作、资源加载等耗费性能的处理,很可能导致界面卡顿,甚至浏览器的崩溃。函数节流(throttle)和函数防抖(debounce)就是为了解决类似需求应运而生的。



    原文链接

    函数节流(throttle)

    函数节流就是预定一个函数只有在大于等于执行周期时才执行,周期内调用不执行。好像水滴攒到一定重量才会落下一样。

    场景:

    • 窗口调整(resize)
    • 页面滚动(scroll)
    • 抢购疯狂点击(mousedown)

    实现:

    function throttle(method, delay){
        var last = 0;
        return function (){
            var now = +new Date();
            if(now - last > delay){
                method.apply(this,arguments);
                last = now;
            }
        }
    }
    
    document.getElementById('throttle').onclick = throttle(function(){console.log('click')},2000);
    

    underscore实现:

    _.throttle = function(func, wait, options) {
        var context, args, result;
        var timeout = null;
        var previous = 0;
        if (!options) options = {};
        var later = function() {
            previous = options.leading === false ? 0 : _.now();
            timeout = null;
            result = func.apply(context, args);
            if (!timeout) context = args = null;
        };
        return function() {
            var now = _.now();
            if (!previous && options.leading === false) previous = now;
            //计算剩余时间
            var remaining = wait - (now - previous);
            context = this;
            args = arguments;
            //剩余时间小于等于0或者剩余时间大于等待时间(本地时间变动出现)
            if (remaining <= 0 || remaining > wait) {
                if (timeout) {
                    clearTimeout(timeout);
                    timeout = null;
                }
                previous = now;
                result = func.apply(context, args);
                if (!timeout) context = args = null;
            } else if (!timeout && options.trailing !== false) {
                timeout = setTimeout(later, remaining);
            }
            return result;
        };
    };    
    

    函数防抖(debounce)

    函数防抖就是在函数需要频繁触发情况时,只有足够空闲的时间,才执行一次。好像公交司机会等人都上车后才出站一样。

    场景:

    • 实时搜索(keyup)
    • 拖拽(mousemove)

    实现:

    function debounce(method, delay){
        var timer = null;
        return function(){
            var context = this,args = arguments;
            clearTimeout(timer);
            timer = setTimeout(function(){
                method.apply(context, args);
            },delay);
        }
    }
    
    document.getElementById('debounce').onclick = debounce(function(){console.log('click')},2000);
    

    underscore实现:

    _.debounce = function(func, wait, immediate) {
        var timeout, args, context, timestamp, result;
        var later = function() {
            var last = _.now() - timestamp;
            if (last < wait && last >= 0) {
                timeout = setTimeout(later, wait - last);
            } else {
                timeout = null;
                if (!immediate) {
                    result = func.apply(context, args);
                    if (!timeout) context = args = null;
                }
            }
        };
        return function() {
            context = this;
            args = arguments;
            timestamp = _.now();
            var callNow = immediate && !timeout;
            if (!timeout) timeout = setTimeout(later, wait);
            if (callNow) {
                result = func.apply(context, args);
                context = args = null;
            }
            return result;
        };
    };    
    

    函数节流(throttle)和函数防抖(debounce)都是通过延时逻辑操作来提升性能的方法,在前端优化中是常见且重要的解决方式。可以从概念和实际应用中理解两者的区别,在需要的时候选择合适的方法处理。

    相关文章

      网友评论

        本文标题:JS函数节流防抖

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