99久久精品国产片-99久久精品国产免费-99久久精品国产麻豆-99久久精品国产国产毛片-99久久精品国产高清一区二区-99久久精品费精品国产一区二区

函數節流與函數防抖的區別

2020-4-29    seo達人

函數節流與函數防抖是我們解決頻繁觸發DOM事件的兩種常用解決方案,但是經常傻傻分不清楚。。。這不,在項目中又用遇到了,在此處記錄一下



函數防抖 debounce

原理:將若干函數調用合成為一次,并在給定時間過去之后,或者連續事件完全觸發完成之后,調用一次(僅僅只會調用一次!!!!!!!!!!)。



舉個栗子:滾動scroll事件,不停滑動滾輪會連續觸發多次滾動事件,從而調用綁定的回調函數,我們希望當我們停止滾動的時,才觸發一次回調,這時可以使用函數防抖。



原理性代碼及測試:



// 給盒子較大的height,容易看到效果

<style>

    * {

        padding: 0;

        margin: 0;

    }



    .box {

        width: 800px;

        height: 1200px;

    }

</style>

<body>

    <div class="container">

        <div class="box" style="background: tomato"></div>

        <div class="box" style="background: skyblue"></div>

        <div class="box" style="background: red"></div>

        <div class="box" style="background: yellow"></div>

    </div>

    <script>

        window.onload = function() {

            const decounce = function(fn, delay) {

                let timer = null



                return function() {

                    const context = this

                    let args = arguments

                    clearTimeout(timer) // 每次調用debounce函數都會將前一次的timer清空,確保只執行一次

                    timer = setTimeout(() => {

                        fn.apply(context, args)

                    }, delay)

                }

            }



            let num = 0



            function scrollTap() {

                num++

                console.log(看看num吧 ${num})

            }

            // 此處的觸發時間間隔設置的很小

            document.addEventListener('scroll', decounce(scrollTap, 500))

            // document.addEventListener('scroll', scrollTap)

        }

    </script>

</body>



此處的觸發時間間隔設置的很小,如果勻速不間斷的滾動,不斷觸發scroll事件,如果不用debounce處理,可以發現num改變了很多次,用了debounce函數防抖,num在一次上時間的滾動中只改變了一次。



調用debouce使scrollTap防抖之后的結果:



直接調用scrollTap的結果:





補充:瀏覽器在處理setTimeout和setInterval時,有最小時間間隔。

setTimeout的最短時間間隔是4毫秒;

setInterval的最短間隔時間是10毫秒,也就是說,小于10毫秒的時間間隔會被調整到10毫秒。

事實上,未優化時,scroll事件頻繁觸發的時間間隔也是這個最小時間間隔。

也就是說,當我們在debounce函數中的間隔事件設置不恰當(小于這個最小時間間隔),會使debounce無效。



函數節流 throttle

原理:當達到了一定的時間間隔就會執行一次;可以理解為是縮減執行頻率



舉個栗子:還是以scroll滾動事件來說吧,滾動事件是及其消耗瀏覽器性能的,不停觸發。以我在項目中碰到的問題,移動端通過scroll實現分頁,不斷滾動,我們不希望不斷發送請求,只有當達到某個條件,比如,距離手機窗口底部150px才發送一個請求,接下來就是展示新頁面的請求,不停滾動,如此反復;這個時候就得用到函數節流。



原理性代碼及實現



// 函數節流 throttle

// 方法一:定時器實現

const throttle = function(fn,delay) {

  let timer = null



  return function() {

    const context = this

    let args = arguments

    if(!timer) {

      timer = setTimeout(() => {

        fn.apply(context,args) 

        clearTimeout(timer) 

      },delay)

    }

  }

}



// 方法二:時間戳

const throttle2 = function(fn, delay) {

  let preTime = Date.now()



  return function() {

      const context = this

      let args = arguments

      let doTime = Date.now()

      if (doTime - preTime >= delay) {

          fn.apply(context, args)

          preTime = Date.now()

      }

  }

}



需要注意的是定時器方法實現throttle方法和debounce方法的不同:



在debounce中:在執行setTimeout函數之前總會將timer用setTimeout清除,取消延遲代碼塊,確保只執行一次

在throttle中:只要timer存在就會執行setTimeout,在setTimeout內部每次清空這個timer,但是延遲代碼塊已經執行啦,確保一定頻率執行一次




我們依舊可以在html頁面中進行測試scroll事件,html和css代碼同debounce,此處不贅述,運行結果是(可以說是一場漫長的滾輪滾動了):





最后再來瞅瞅項目中封裝好的debounce和throttle函數,可以說是很優秀了,考慮的特別全面,希望自己以后封裝的函數也能考慮的這么全面吧,加油!



/*

 
空閑控制 返回函數連續調用時,空閑時間必須大于或等于 wait,func 才會執行

 

 
@param  {function} func        傳入函數,最后一個參數是額外增加的this對象,.apply(this, args) 這種方式,this無法傳遞進函數

  @param  {number}   wait        表示時間窗口的間隔

 
@param  {boolean}  immediate   設置為ture時,調用觸發于開始邊界而不是結束邊界

  @return {function}             返回客戶調用函數

 
/

const debounce = function(func, wait, immediate) {

    let timeout, args, context, timestamp, result;



    const later = function() {

        // 據上一次觸發時間間隔

        let last = Number(new Date()) - timestamp;



        // 上次被包裝函數被調用時間間隔last小于設定時間間隔wait

        if (last < wait && last > 0) {

            timeout = setTimeout(later, wait - last);

        } else {

            timeout = null;

            // 如果設定為immediate===true,因為開始邊界已經調用過了此處無需調用

            if (!immediate) {

                result = func.call(context, ...args, context);

                if (!timeout) {

                    context = args = null;

                }

            }

        }

    };



    return function(..._args) {

        context = this;

        args = _args;

        timestamp = Number(new Date());

        const callNow = immediate && !timeout;

        // 如果延時不存在,重新設定延時

        if (!timeout) {

            timeout = setTimeout(later, wait);

        }

        if (callNow) {

            result = func.call(context, ...args, context);

            context = args = null;

        }



        return result;

    };

};



/*

 
頻率控制 返回函數連續調用時,func 執行頻率限定為 次 / wait

 

 
@param  {function}   func      傳入函數

  @param  {number}     wait      表示時間窗口的間隔

 
@param  {object}     options   如果想忽略開始邊界上的調用,傳入{leading: false}。

                                 如果想忽略結尾邊界上的調用,傳入{trailing: false}

 
@return {function}             返回客戶調用函數

 */

const throttle = function(func, wait, options) {

    let context, args, result;

    let timeout = null;

    // 上次執行時間點

    let previous = 0;

    if (!options) options = {};

    // 延遲執行函數

    let later = function() {

        // 若設定了開始邊界不執行選項,上次執行時間始終為0

        previous = options.leading === false ? 0 : Number(new Date());

        timeout = null;

        result = func.apply(context, args);

        if (!timeout) context = args = null;

    };

    return function(..._args) {

        let now = Number(new Date());

        // 首次執行時,如果設定了開始邊界不執行選項,將上次執行時間設定為當前時間。

        if (!previous && options.leading === false) previous = now;

        // 延遲執行時間間隔

        let remaining = wait - (now - previous);

        context = this;

        args = _args;

        // 延遲時間間隔remaining小于等于0,表示上次執行至此所間隔時間已經超過一個時間窗口

        // remaining大于時間窗口wait,表示客戶端系統時間被調整過

        if (remaining <= 0 || remaining > wait) {

            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;

    };

};


日歷

鏈接

個人資料

藍藍設計的小編 http://www.lapeinture.cn

存檔

日韩免费在线视频| 国产伦理精品| 中文字幕一区二区三区 精品 | 国产精品自拍在线| 黄色免费三级| 精品视频一区二区三区免费| 人人干人人草| 欧美国产日韩久久久| 国产精品自拍在线| 91麻豆精品国产自产在线观看一区| 成人a大片高清在线观看| 国产成人精品影视| 日本在线不卡视频| 天天色色色| 午夜精品国产自在现线拍| 国产视频在线免费观看| 亚洲 欧美 91| 九九精品在线| 免费一级片在线| 香蕉视频三级| 天堂网中文字幕| 国产精品免费精品自在线观看| 精品视频一区二区三区免费| 黄色免费网站在线| 欧美日本韩国| 日日日夜夜操| 国产精品1024永久免费视频| 国产美女在线观看| 日韩男人天堂| 亚洲精品影院| 欧美爱色| 久久国产精品自线拍免费| 韩国三级一区| 日日日夜夜操| 日韩中文字幕一区二区不卡| 久久精品道一区二区三区| 日本在线播放一区| 一级毛片视频免费| 美女免费精品高清毛片在线视 | a级黄色毛片免费播放视频| 国产一区二区高清视频| 日本免费乱人伦在线观看| 亚洲精品久久久中文字| 日韩专区亚洲综合久久| 97视频免费在线| 99久久精品国产免费| 国产视频在线免费观看| 久久99这里只有精品国产| 人人干人人草| 超级乱淫黄漫画免费| 二级特黄绝大片免费视频大片| 一级毛片视频免费| 国产一级生活片| 精品视频一区二区| 国产视频一区二区在线观看| 欧美一级视频免费观看| 日韩专区一区| 精品美女| 91麻豆精品国产综合久久久| 人人干人人草| 久久精品道一区二区三区| 精品视频一区二区三区| 精品国产一区二区三区国产馆| 99热热久久| 成人高清视频免费观看| 欧美α片无限看在线观看免费| 日本特黄特色aaa大片免费| 久久国产一久久高清| 成人高清免费| 台湾毛片| 午夜欧美成人久久久久久| 日韩免费片| 欧美日本二区| 国产极品白嫩美女在线观看看| 成人免费一级毛片在线播放视频| 成人高清视频免费观看| 九九干| 日韩在线观看视频黄| 青青青草影院 | 精品在线视频播放| 国产一区二区高清视频| 九九久久国产精品大片| 四虎影视库国产精品一区| 高清一级片| 欧美另类videosbestsex高清| 一级片片| 日韩专区一区| 国产亚洲男人的天堂在线观看| 亚洲第一页色| 欧美激情影院| 国产a毛片| 亚洲天堂免费观看| 日本在线不卡视频| 久久国产影视免费精品| 亚洲爆爽| 久久久久久久免费视频| 成人免费网站视频ww| 日韩在线观看网站| 日日日夜夜操| 亚洲精品久久久中文字| 中文字幕一区二区三区 精品| 黄视频网站免费观看| 国产精品123| 精品久久久久久中文字幕一区| 精品国产一区二区三区免费 | 国产91精品一区二区| 国产91精品露脸国语对白| 青青久久精品| 国产一区二区精品| 亚洲精品中文一区不卡| 九九九国产| 日本特黄特黄aaaaa大片| 黄色短视频网站| 中文字幕Aⅴ资源网| 日韩免费在线视频| 日韩在线观看视频网站| 青草国产在线| 99久久网站| 日韩欧美一及在线播放| 午夜欧美福利| 精品久久久久久免费影院| 亚洲第一色在线| 国产精品自拍亚洲| 日本特黄特色aa大片免费| 欧美激情一区二区三区在线 | 好男人天堂网 久久精品国产这里是免费 国产精品成人一区二区 男人天堂网2021 男人的天堂在线观看 丁香六月综合激情 | 国产伦久视频免费观看视频| 欧美日本免费| 天堂网中文字幕| 久久福利影视| 国产欧美精品午夜在线播放| 天堂网中文在线| 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 欧美日本免费| 日韩在线观看视频黄| 国产精品1024永久免费视频| 国产一区精品| 毛片高清| 91麻豆国产级在线| 九九久久国产精品| 欧美大片aaaa一级毛片| 日本免费看视频| 国产一区二区精品久久91| 日韩在线观看视频黄| 国产成a人片在线观看视频| 91麻豆高清国产在线播放| 天天色色色| 青青久在线视频| 成人免费一级毛片在线播放视频| 香蕉视频久久| 精品在线视频播放| 一本高清在线| 日本特黄特黄aaaaa大片| 91麻豆精品国产综合久久久| 国产a视频精品免费观看| 亚洲 国产精品 日韩| 国产成人精品综合在线| 国产一区精品| 欧美激情一区二区三区在线播放 | 欧美日本免费| 国产麻豆精品高清在线播放| 青青久久精品| 一本高清在线| 国产国语对白一级毛片| 亚洲www美色| 精品视频免费在线| 久久久久久久免费视频| 黄色免费网站在线| 中文字幕一区二区三区 精品| 日韩在线观看网站| 久久精品成人一区二区三区| a级黄色毛片免费播放视频| 亚洲第一页色| 韩国毛片基地| 亚洲天堂在线播放| 日韩一级精品视频在线观看| 你懂的国产精品| 一级毛片视频播放| 精品久久久久久中文字幕一区| 国产一级强片在线观看| 一本高清在线| 成人av在线播放| 国产不卡精品一区二区三区| 欧美日本韩国| 欧美爱色| 高清一级毛片一本到免费观看| 成人高清视频免费观看| 99热精品一区| 精品在线视频播放| 亚飞与亚基在线观看| 亚洲第一色在线| 成人免费观看的视频黄页| 亚欧乱色一区二区三区| 香蕉视频久久| 四虎影视精品永久免费网站 | 国产高清视频免费| 久久成人亚洲| 国产一区二区精品久久91| 青青青草影院 | 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 |