函数节流与去抖

https://github.com/hahnzhu/read-code-per-day/issues/5

 又被坑了。。。

函数节流

函数节流英文为 throttle,其翻译是「节流阀、压制、减速」,很形象地表达了它的作用就是控制函数的调用频度,但为什么需要减少函数的调用频度呢?因为某些场景下一些 DOM 事件会鬼畜般触发(如 mousemove、scroll、resize 等);或者一个抽奖页中,某个人帕金森综合征病发般点击抽奖按钮。这个时候假如事件绑定了函数的话,就会频繁调用,甚至导致某些浏览器奔溃(一种叫 IE 的浏览器)。

函数节流的原理

函数节流应用非常广,在很多源码中都会出现。其原理就是定时器。当事件触发时,通过 setTimeout 让这个事件延迟一会再执行,如果在这个时间间隔内该事件又被触发了,那就 clear 掉原来的定时器,重新setTimeout 一个新的定时器延迟一会执行,就酱紫。上代码:

 

1、就是这样实现

 

 var resizeTimer = null;
    $(window).on('resize', function () {
        /* 第一次访问,不存在 resizeTimer,跳过这里 */
        if (resizeTimer) {
            clearTimeout(resizeTimer);
        }
        /* 第一次访问,赋值给 resizeTimer,绑定的函数 400ms 后调用 */
        resizeTimer = setTimeout(function(){
            console.log("window resize");
        }, 400);
    });
    var touchMoveTimer = null;

    $(window).on("touchmove",function(){
        /* 第一次访问,不存在 resizeTimer,跳过这里 */
        if (touchMoveTimer) {
            clearTimeout(touchMoveTimer);
        }
        /* 第一次访问,赋值给 resizeTimer,绑定的函数 400ms 后调用 */
        touchMoveTimer = setTimeout(function(){
            console.log("touchmove...");
        }, 400);
    });

 

2、《JavaScript高级程序设计》

function throttle(method, context) {
        console.log(method.tId);
        clearTimeout(method.tId);
        method.tId = setTimeout(function(){
            method.call(context);
        }, 300);
    };

下面是我的调用方法:

$(window).on("touchmove",function(){
        throttle(function(){
            //每次都是不同的function
            console.log("touchmove-----inner");
        });
    });

明显错了,因为touchmove的时候执行throttle。传进去的method每次都是一个新的函数啊。。。

类似下面这个。。

$(window).on("touchmove",function(){
        var a = function(){
            console.log("touchmove-----inner");
        };
        throttle(a);
    });

正确的姿势是:

var a = function(){
        console.log("touchmove-----inner");
    };
    $(window).on("touchmove",function(){
        throttle(a);
    });

3、impress.js实现

var throttle2 = function(fn, delay){
        var timer = null;
        return function(){
            var context = this, args = arguments;
            clearTimeout(timer);
            timer = setTimeout(function(){
                fn.apply(context, args);
            }, delay);
        }
    }
    var myFunc = function(){
        console.log("touchmove--inner");
    };
    $(window).on("touchmove",throttle2(myFunc, 400))

 

posted @ 2016-04-05 10:09  darr  阅读(291)  评论(0编辑  收藏  举报