zoukankan      html  css  js  c++  java
  • JS 节流阀

    JS 节流阀

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

    节流阀

    节流阀的基本原理
    事件函数的执行都记下当前时间, 只有当前时间与上次执行时间有一定间隔的时候才会去执行真正的逻辑

        function throttleMe(cb){
            console.log('move');
            var start = +new Date();
            return function(){
                var now = new Date();
                if(now - start > 1000){
                    start  = now;
                    cb();
                }
            }
        }
        $(window).on('mousemove', throttleMe(function(){
            console.log('timer');
        }));
    

    有的书上是这么实现的 这个并不好用

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

    发现实际中并不是40ms调用一次move timer
    原因就在于timeout 它是等这个函数执行完之后间隔40ms 才有机会去执行下一个函数

        function throttle(func, wait) {
            var context, args, timeout, result;
            var previous = 0;
            var later = function() {
                previous = +new Date();
                timeout = null;
                result = func.apply(context, args);
            };
            return function() {
                var now = +new Date();
                var remaining = wait - (now - previous); //距离下次执行剩余时间
                console.log('remaining'+remaining + 'now'+ now);
                context = this;
                args = arguments;
                if (remaining <= 0) { //过了间隔时间段  开始执行
                    clearTimeout(timeout);
                    timeout = null;
                    previous = now;
                    console.log('<0<0<0');
                    result = func.apply(context, args);
                } else if (!timeout) {
                    console.log('set time out------------');
                    timeout = setTimeout(later, remaining);
                }
                return result;
            };
        }
    

    函数去抖

        function debounce(fn, threshhold, scope) {
            threshhold || (threshhold = 250);
            var last,
                deferTimer;
            return function() {
                console.log('move');// 这个函数是mousemove事件处理的函数
                var context = scope || this;
    
                var now = +new Date,
                    args = arguments;
                if (last && now < last + threshhold) {
                    // hold on to it
                    clearTimeout(deferTimer);
                    deferTimer = setTimeout(function() {
                        last = now;
                        fn.apply(context, args);
                    }, threshhold);
                } else {
                    last = now;
                    fn.apply(context, args);
                }
            };
        }
        $('body').on('mousemove', function() {
            console.log('move');
        });
        $('body').on('mousemove', debounce(function(event) {
            console.log('tick');
        }, 1000));
    

    每次mousemove都是在执行 debounce返回的一个函数
    这个返回的函数用到了debounce中的一个变量last
    奇怪! 这个last 又不是全局的变量 为什么这个函数每次执行都依赖上次last的结果? 因为这里是一个闭包

    通过闭包 使局部变量变成全局变量

    因为这个a后面一直被fun函数使用 所以这个变量不会被销毁 正是闭包特性

    function closure(){
        var a = 1;
        return function(){
            return ++a;
        }
    }
    fun = closure();
    console.log(fun());//2
    console.log(fun());//3
    console.log(fun());//4
    
  • 相关阅读:
    P1135 奇怪的电梯题解
    P1443 马的遍历题解
    P2392 kkksc03考前临时抱佛脚题解
    P1219 八皇后问题题解
    IDEA导入/导出live templates或者其他设置
    P3743 kotori的设备题解
    带你看论文丨全局信息对于图网络文档解析的影响
    【“互联网+”大赛华为云赛道】EI命题攻略:华为云EI的能力超丰富,助你实现AI梦想
    【“互联网+”大赛华为云赛道】IoT命题攻略:仅需四步,轻松实现场景智能化设计
    只需6步,教你从零开发一个签到小程序
  • 原文地址:https://www.cnblogs.com/cart55free99/p/4717236.html
Copyright © 2011-2022 走看看