国产黄色免费网站_久久天天做天天爱综合色_精品国产一区久久久_成人黄色激情网站_久久成人在线视频_美女一区二区在线观看_亚洲精品免费一区亚洲精品免费精品一区 _91精品国产综合久久精品麻豆

函數(shù)節(jié)流與函數(shù)防抖的區(qū)別

2020-4-29    seo達(dá)人

函數(shù)節(jié)流與函數(shù)防抖是我們解決頻繁觸發(fā)DOM事件的兩種常用解決方案,但是經(jīng)常傻傻分不清楚。。。這不,在項(xiàng)目中又用遇到了,在此處記錄一下



函數(shù)防抖 debounce

原理:將若干函數(shù)調(diào)用合成為一次,并在給定時(shí)間過去之后,或者連續(xù)事件完全觸發(fā)完成之后,調(diào)用一次(僅僅只會(huì)調(diào)用一次!!!!!!!!!!)。



舉個(gè)栗子:滾動(dòng)scroll事件,不停滑動(dòng)滾輪會(huì)連續(xù)觸發(fā)多次滾動(dòng)事件,從而調(diào)用綁定的回調(diào)函數(shù),我們希望當(dāng)我們停止?jié)L動(dòng)的時(shí),才觸發(fā)一次回調(diào),這時(shí)可以使用函數(shù)防抖。



原理性代碼及測(cè)試:



// 給盒子較大的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) // 每次調(diào)用debounce函數(shù)都會(huì)將前一次的timer清空,確保只執(zhí)行一次

                    timer = setTimeout(() => {

                        fn.apply(context, args)

                    }, delay)

                }

            }



            let num = 0



            function scrollTap() {

                num++

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

            }

            // 此處的觸發(fā)時(shí)間間隔設(shè)置的很小

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

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

        }

    </script>

</body>



此處的觸發(fā)時(shí)間間隔設(shè)置的很小,如果勻速不間斷的滾動(dòng),不斷觸發(fā)scroll事件,如果不用debounce處理,可以發(fā)現(xiàn)num改變了很多次,用了debounce函數(shù)防抖,num在一次上時(shí)間的滾動(dòng)中只改變了一次。



調(diào)用debouce使scrollTap防抖之后的結(jié)果:



直接調(diào)用scrollTap的結(jié)果:





補(bǔ)充:瀏覽器在處理setTimeout和setInterval時(shí),有最小時(shí)間間隔。

setTimeout的最短時(shí)間間隔是4毫秒;

setInterval的最短間隔時(shí)間是10毫秒,也就是說,小于10毫秒的時(shí)間間隔會(huì)被調(diào)整到10毫秒。

事實(shí)上,未優(yōu)化時(shí),scroll事件頻繁觸發(fā)的時(shí)間間隔也是這個(gè)最小時(shí)間間隔。

也就是說,當(dāng)我們?cè)赿ebounce函數(shù)中的間隔事件設(shè)置不恰當(dāng)(小于這個(gè)最小時(shí)間間隔),會(huì)使debounce無效。



函數(shù)節(jié)流 throttle

原理:當(dāng)達(dá)到了一定的時(shí)間間隔就會(huì)執(zhí)行一次;可以理解為是縮減執(zhí)行頻率



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



原理性代碼及實(shí)現(xiàn)



// 函數(shù)節(jié)流 throttle

// 方法一:定時(shí)器實(shí)現(xiàn)

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)

    }

  }

}



// 方法二:時(shí)間戳

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()

      }

  }

}



需要注意的是定時(shí)器方法實(shí)現(xiàn)throttle方法和debounce方法的不同:



在debounce中:在執(zhí)行setTimeout函數(shù)之前總會(huì)將timer用setTimeout清除,取消延遲代碼塊,確保只執(zhí)行一次

在throttle中:只要timer存在就會(huì)執(zhí)行setTimeout,在setTimeout內(nèi)部每次清空這個(gè)timer,但是延遲代碼塊已經(jīng)執(zhí)行啦,確保一定頻率執(zhí)行一次




我們依舊可以在html頁(yè)面中進(jìn)行測(cè)試scroll事件,html和css代碼同debounce,此處不贅述,運(yùn)行結(jié)果是(可以說是一場(chǎng)漫長(zhǎng)的滾輪滾動(dòng)了):





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



/*

 
空閑控制 返回函數(shù)連續(xù)調(diào)用時(shí),空閑時(shí)間必須大于或等于 wait,func 才會(huì)執(zhí)行

 

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

  @param  {number}   wait        表示時(shí)間窗口的間隔

 
@param  {boolean}  immediate   設(shè)置為ture時(shí),調(diào)用觸發(fā)于開始邊界而不是結(jié)束邊界

  @return {function}             返回客戶調(diào)用函數(shù)

 
/

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

    let timeout, args, context, timestamp, result;



    const later = function() {

        // 據(jù)上一次觸發(fā)時(shí)間間隔

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



        // 上次被包裝函數(shù)被調(diào)用時(shí)間間隔last小于設(shè)定時(shí)間間隔wait

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

            timeout = setTimeout(later, wait - last);

        } else {

            timeout = null;

            // 如果設(shè)定為immediate===true,因?yàn)殚_始邊界已經(jīng)調(diào)用過了此處無需調(diào)用

            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;

        // 如果延時(shí)不存在,重新設(shè)定延時(shí)

        if (!timeout) {

            timeout = setTimeout(later, wait);

        }

        if (callNow) {

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

            context = args = null;

        }



        return result;

    };

};



/*

 
頻率控制 返回函數(shù)連續(xù)調(diào)用時(shí),func 執(zhí)行頻率限定為 次 / wait

 

 
@param  {function}   func      傳入函數(shù)

  @param  {number}     wait      表示時(shí)間窗口的間隔

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

                                 如果想忽略結(jié)尾邊界上的調(diào)用,傳入{trailing: false}

 
@return {function}             返回客戶調(diào)用函數(shù)

 */

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

    let context, args, result;

    let timeout = null;

    // 上次執(zhí)行時(shí)間點(diǎn)

    let previous = 0;

    if (!options) options = {};

    // 延遲執(zhí)行函數(shù)

    let later = function() {

        // 若設(shè)定了開始邊界不執(zhí)行選項(xiàng),上次執(zhí)行時(shí)間始終為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());

        // 首次執(zhí)行時(shí),如果設(shè)定了開始邊界不執(zhí)行選項(xiàng),將上次執(zhí)行時(shí)間設(shè)定為當(dāng)前時(shí)間。

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

        // 延遲執(zhí)行時(shí)間間隔

        let remaining = wait - (now - previous);

        context = this;

        args = _args;

        // 延遲時(shí)間間隔remaining小于等于0,表示上次執(zhí)行至此所間隔時(shí)間已經(jīng)超過一個(gè)時(shí)間窗口

        // remaining大于時(shí)間窗口wait,表示客戶端系統(tǒng)時(shí)間被調(diào)整過

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

            clearTimeout(timeout);

            timeout = null;

            previous = now;

            result = func.apply(context, args);

            if (!timeout) context = args = null;

            //如果延遲執(zhí)行不存在,且沒有設(shè)定結(jié)尾邊界不執(zhí)行選項(xiàng)

        } else if (!timeout && options.trailing !== false) {

            timeout = setTimeout(later, remaining);

        }

        return result;

    };

};


日歷

鏈接

個(gè)人資料

藍(lán)藍(lán)設(shè)計(jì)的小編 http://www.newchinaweekly.com

存檔

久久97超碰色| 人人干人人干人人干| 老女人性淫交视频| 97人人澡人人爽| 日韩中文视频免费在线观看| 欧美成人猛片aaaaaaa| 亚洲午夜电影在线| 欧美亚洲尤物久久| 亚洲午夜激情网页| 精品欧美久久久| 欧美精品一区在线播放| 成人av色在线观看| 日本高清视频精品| 欧美激情在线有限公司| 欧美裸体xxxx极品少妇| 91久久精品在线| 乱子伦一区二区| 乱熟女高潮一区二区在线| 五月天婷婷亚洲| 青娱乐国产在线视频| 天堂网av2014| 人与动性xxxxx免费视频| 午夜免费入口| 韩国三级在线观看久| av免费在线一区二区三区| 国产日韩精品在线看| 校园春色亚洲色图| 欧美gayvideo| 99国产精品国产精品久久| a亚洲天堂av| 精品视频1区2区| 日韩一区二区三区四区| 国内精品美女av在线播放| 欧美日韩国产精品一区二区| 亚洲视频电影| 欧洲精品视频在线| 少妇户外露出[11p]| 中文在线观看免费高清| 黄网站在线观看高清免费| 嫩草影院入口一二三| 欧美人xxx| 精品国产乱码久久久| 色综合五月天| 国产亚洲毛片| 一区二区三区视频在线看| 亚洲精品综合久久中文字幕| 久久精品国产亚洲精品2020| 欧美xxxx黑人又粗又长精品| 国产国语老龄妇女a片| 999av视频| 调教视频在线观看| 亚洲国产欧美在线观看| 欧美丰满日韩| 国产日韩av一区二区| 国产视频亚洲精品| 久久久久久亚洲精品不卡4k岛国| 免费观看国产视频在线| 日本黄色录像视频| 国产短剧电视剧免费观看| 16—17女人毛片毛片| 日本免费在线视频| 国产精品毛片久久| 亚洲免费在线观看视频| 91.com在线观看| 成人综合网网址| 国产sm在线观看| 久久久久99精品成人片毛片| 免费大秀视频在线播放| 国产一区二区色噜噜| 欧美手机视频| 日韩在线卡一卡二| 中文字幕免费在线观看视频一区| 欧美视频专区一二在线观看| 青青草成人在线| xxww在线观看| 欧美一级高潮片| 成人久久在线| 探花国产精品| 亚洲精品亚洲人成在线| 国产欧美精品一区aⅴ影院 | 国产精品综合色区在线观看| 欧美三级日韩三级| 国产精品一区在线播放| 青青在线免费观看| 在线观看日本网站| 蜜桃视频在线入口www| 欧美成人久久| 国产日产精品1区| 欧美精品免费在线| 亚洲中文字幕久久精品无码喷水| 一色道久久88加勒比一| 免费观看又色又爽又黄的网站| 日韩三级精品| 亚洲精品国产无天堂网2021| 国产女人18毛片水18精品| 国产激情第一页| 99久久婷婷国产一区二区三区| 麻豆网在线观看| 日韩1区2区日韩1区2区| 欧美视频二区36p| 肥熟一91porny丨九色丨| 午夜剧场免费在线观看| 亲爱的老师6电影韩剧| 美州a亚洲一视本频v色道| 狠狠噜噜久久| 伊人婷婷欧美激情| 91亚洲午夜在线| 久艹视频在线观看| 男男电影完整版在线观看| 视频精品一区二区| 中文字幕亚洲激情| 国产999免费视频| 涩涩视频免费观看| 日韩电影免费网站| 欧美顶级少妇做爰| 亚洲a∨日韩av高清在线观看| 日本人视频jizz页码69| 在线免费观看一级片| 国产高潮av| www.爱久久| 久久色中文字幕| 国产精品视频大全| www.污网站| 极度色播免费播放视频| 欧美精品1区| 欧美日韩综合视频网址| 亚洲va韩国va欧美va精四季| 888奇米影视| 日韩电影精品| 欧美视频在线观看免费| av磁力番号网| 久色视频在线观看| 亚洲亚洲免费| 亚洲成人激情在线| 91香蕉视频在线观看视频| 99热在线观看免费| 日本aⅴ免费视频一区二区三区| 欧美激情影音先锋| 成人免费黄色小视频| wwwwwww色| 99成人在线| 欧美激情精品在线| 国产黄在线免费观看| 超碰最新在线| 久久99精品国产麻豆婷婷| 51色欧美片视频在线观看| 国产在线一二区| 成人国产二区| 2022国产精品视频| 美女久久久久久久| 99国产精品无码| 91污色多多| 重囗味另类老妇506070| 欧美性猛交一区二区三区精品| 日韩免费一级视频| 日韩一区二区三区在线观看视频| 国产黄色在线网站| 最新国产成人在线观看| 91中文字幕在线| 国产剧情久久久| 超碰中文在线| 91亚洲精品久久久蜜桃| 精品日本一区二区| 四虎永久网址| 国产真实久久| 国产va免费精品高清在线观看| a片在线免费观看| 大片免费在线观看| 亚洲国产成人tv| 欧美黑人又粗又大又爽免费| 91热爆在线观看| 国产精品久久国产愉拍| 国产精品扒开腿做| 手机在线免费看毛片| 在线观看v片| 欧美丰满一区二区免费视频 | 国产网站免费看| 久久精品毛片| 国产精品视频免费一区二区三区| 男女下面一进一出无遮挡| 亚洲国产欧美国产综合一区| 精品国产sm最大网站| 亚欧洲乱码视频| av高清不卡| 精品成人在线观看| 小早川怜子一区二区的演员表| 国产日本久久| 亚洲欧美制服丝袜| 久久精品日产第一区二区三区精品版| 亚洲久草视频| 久久99精品久久久| 一级做a爰片久久| xxxxx国产| 一区二区三区四区不卡在线| 亚洲综合123| 大胆人体一区| 一个人看的www久久| 伊人久久一区二区| 99精品国产在热久久| 久久狠狠久久综合桃花|