亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

JavaScript性能優化之函數節流(throttle)與函數去抖(debounce)

2019-11-20 09:15:41
字體:
來源:轉載
供稿:網友

函數節流,簡單地講,就是讓一個函數無法在很短的時間間隔內連續調用,只有當上一次函數執行后過了你規定的時間間隔,才能進行下一次該函數的調用。

函數節流的原理挺簡單的,估計大家都想到了,那就是定時器。當我觸發一個時間時,先setTimout讓這個事件延遲一會再執行,如果在這個時間間隔內又觸發了事件,那我們就clear掉原來的定時器,再setTimeout一個新的定時器延遲一會執行,就這樣。

以下場景往往由于事件頻繁被觸發,因而頻繁執行DOM操作、資源加載等重行為,導致UI停頓甚至瀏覽器崩潰。

1. window對象的resize、scroll事件

2. 拖拽時的mousemove事件

3. 射擊游戲中的mousedown、keydown事件

4. 文字輸入、自動完成的keyup事件

實際上對于window的resize事件,實際需求大多為停止改變大小n毫秒后執行后續處理;而其他事件大多的需求是以一定的頻率執行后續處理。針對這兩種需求就出現了debounce和throttle兩種解決辦法。

throttle 和 debounce 是解決請求和響應速度不匹配問題的兩個方案。二者的差異在于選擇不同的策略。

throttle 等時間 間隔執行函數。

debounce 時間間隔 t 內若再次觸發事件,則重新計時,直到停止時間大于或等于 t 才執行函數。

一、throttle函數的簡單實現

function throttle(fn, threshhold, scope) { threshhold || (threshhold = 250); var last, timer; return function () { var context = scope || this; var now = +new Date(), args = arguments; if (last && now - last + threshhold < 0) { // hold on to it clearTimeout(deferTimer); timer = setTimeout(function () { last = now; fn.apply(context, args); }, threshhold); } else { last = now; fn.apply(context, args); } };}

調用方法

$('body').on('mousemove', throttle(function (event) {console.log('tick');}, 1000));

二、debounce函數的簡單實現

function debounce(fn, delay) { var timer = null; return function () { var context = this,args = arguments; clearTimeout(timer); timer = setTimeout(function () { fn.apply(context, args); }, delay); };}

調用方法

$('input.username').keypress(debounce(function (event){// do the Ajax request}, 250));

三、簡單的封裝實現

/** * throttle * @param fn, wait, debounce */var throttle = function ( fn, wait, debounce ) { var timer = null, // 定時器 t_last = null, // 上次設置的時間 context, // 上下文 args, // 參數 diff; // 時間差 return funciton () { var curr = + new Date(); var context = this, args = arguments; clearTimeout( timer ); if ( debounce ) { // 如果是debounce timer = setTimeout( function () { fn.apply( context, args ); }, wait ); } else { // 如果是throttle if ( !t_last ) t_last = curr; if ( curr - t_last >= wait ) { fn.apply( context, wait ); context = wait = null; } } }}/** * debounce * @param fn, wait */var debounce = function ( fn, wait ) { return throttle( fn, wait, true );}

小結:這兩個方法適用于會重復觸發的一些事件,如:mousemove,keydown,keyup,keypress,scroll等。
如果只綁定原生事件,不加以控制,會使得瀏覽器卡頓,用戶體驗差。為了提高js性能,建議在使用以上及類似事件的時候用函數節流或者函數去抖加以控制。

四、underscore v1.7.0相關的源碼剖析                          

1. _.throttle函數

_.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; // 這里引入了一個remaining的概念:還剩多長時間執行事件 var remaining = wait - (now - previous); context = this; args = arguments; // remaining <= 0 考慮到事件停止后重新觸發或者 // 正好相差wait的時候,這些情況下,會立即觸發事件 // remaining > wait 沒有考慮到相應場景 // 因為now-previous永遠都是正值,且不為0,那么 // remaining就會一直比wait小,沒有大于wait的情況 // 估計是保險起見吧,這種情況也是立即執行 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; };};

由上可見,underscore考慮了比較多的情況:options.leading:

第一次是否執行,默認為true,表示第一次會執行,傳入{leading:false}則禁用第一次執行options.trailing:最后一次是否執行,默認為true,表示最后一次會執行,傳入{trailing: false}表示最后一次不執行所謂第一次是否執行,是剛開始觸發事件時,要不要先觸發事件,如果要,則previous=0,remaining 為負值,則立即調用了函數所謂最后一次是否執行,是事件結束后,最后一次觸發了此方法,如果要執行,則設置定時器,即事件結束以后還要在執行一次。remianing > wait 表示客戶端時間被修改過。

2. _.debounce函數

_.debounce = function(func, wait, immediate) { // immediate默認為false var timeout, args, context, timestamp, result; var later = function() { // 當wait指定的時間間隔期間多次調用_.debounce返回的函數,則會不斷更新timestamp的值,導致last < wait && last >= 0一直為true,從而不斷啟動新的計時器延時執行func 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(); // 第一次調用該方法時,且immediate為true,則調用func函數 var callNow = immediate && !timeout; // 在wait指定的時間間隔內首次調用該方法,則啟動計時器定時調用func函數 if (!timeout) timeout = setTimeout(later, wait); if (callNow) { result = func.apply(context, args); context = args = null; } return result; };};

_.debounce實現的精彩之處我認為是通過遞歸啟動計時器來代替通過調用clearTimeout來調整調用func函數的延時執行。

以上所述是小編給大家介紹的JavaScript性能優化之函數節流(throttle)與函數去抖(debounce),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
高清亚洲成在人网站天堂| 日韩高清av一区二区三区| 欧美在线精品免播放器视频| 日韩在线观看免费全集电视剧网站| 欧美成人免费va影院高清| 奇米四色中文综合久久| 欧美日韩另类字幕中文| 国模视频一区二区| 国产精品男人的天堂| 国内揄拍国内精品少妇国语| 国产免费成人av| 最近2019免费中文字幕视频三| 日本道色综合久久影院| 亚洲大胆美女视频| 中文字幕在线国产精品| 亚洲国产成人精品久久| 91热精品视频| 日韩中文有码在线视频| 成人免费福利在线| 国模视频一区二区三区| 欧美贵妇videos办公室| 亚洲www在线观看| 欧美黑人巨大xxx极品| 中文字幕日韩有码| 久久久久久999| 欧美性猛交xxxx乱大交| 欧美与欧洲交xxxx免费观看| 亚洲美女www午夜| 成人福利免费观看| 亚洲午夜精品视频| 欧美性高潮床叫视频| 亚洲久久久久久久久久久| 国产精品福利在线| 久久亚洲精品一区二区| 国产91av在线| 日韩视频免费看| 国产精品男女猛烈高潮激情| 亚洲精品久久久久中文字幕欢迎你| 国产成人avxxxxx在线看| 国产在线一区二区三区| 国产不卡视频在线| 亚洲999一在线观看www| 亚洲国产精品久久91精品| 亚洲欧美成人在线| 68精品国产免费久久久久久婷婷| 国产精品视频男人的天堂| 亚洲欧美成人网| 国产+人+亚洲| 中文字幕av一区| 国内精品美女av在线播放| 91久久久久久久久久久| 亚洲视频电影图片偷拍一区| 美女黄色丝袜一区| 热re91久久精品国99热蜜臀| 久久影院在线观看| 日韩av三级在线观看| 中文综合在线观看| 日韩成人在线电影网| 国产精品嫩草影院一区二区| 久久久久免费精品国产| 欧美精品九九久久| 欧美日韩国产一中文字不卡| 欧美成人黄色小视频| 欧美激情一区二区久久久| 国产www精品| 久久精品国产欧美激情| 51视频国产精品一区二区| 成人午夜一级二级三级| 国产第一区电影| 国产91色在线播放| 色偷偷综合社区| 亚洲第一精品福利| 精品国产一区二区三区久久久| 欧美视频中文字幕在线| 欧美激情高清视频| 国产www精品| 亚洲高清一区二| 秋霞成人午夜鲁丝一区二区三区| 91黑丝在线观看| 久久精品最新地址| 亚洲国产成人爱av在线播放| 亚洲视频电影图片偷拍一区| 中文综合在线观看| 992tv在线成人免费观看| 亚洲第一区第一页| 色婷婷综合久久久久中文字幕1| 国产精品免费看久久久香蕉| 精品亚洲va在线va天堂资源站| 久久69精品久久久久久国产越南| 亚洲欧美激情在线视频| 精品色蜜蜜精品视频在线观看| 久久精品99国产精品酒店日本| 亚洲日本成人网| 亚洲韩国欧洲国产日产av| 欧美成人黄色小视频| 亚洲第一在线视频| 日韩中文在线中文网三级| 中文字幕无线精品亚洲乱码一区| 97人洗澡人人免费公开视频碰碰碰| 日韩成人性视频| 亚洲欧美国产视频| 欧美极品欧美精品欧美视频| 91色视频在线观看| 国产日韩欧美在线播放| 国产午夜精品全部视频在线播放| 亚州成人av在线| 久久久久久亚洲精品不卡| 色综合男人天堂| 91精品国产乱码久久久久久蜜臀| 亚洲影院色在线观看免费| 日韩精品在线电影| 一区二区三区四区视频| 国产精品91免费在线| 久久久亚洲网站| 7m精品福利视频导航| 国产精品久久久久久久久久久不卡| 欧美一区二区三区四区在线| 美女性感视频久久久| 日本老师69xxx| 日韩国产精品亚洲а∨天堂免| 欧洲成人在线视频| 欧美夜福利tv在线| 国产拍精品一二三| 国产日韩欧美夫妻视频在线观看| 日本精品免费一区二区三区| 美女国内精品自产拍在线播放| 成人在线观看视频网站| 45www国产精品网站| 亚洲国产另类 国产精品国产免费| 日韩黄色高清视频| 国产精品欧美激情在线播放| 国产精品美女久久久久久免费| 欧美一区二区三区四区在线| 日韩欧美黄色动漫| 欧美精品在线第一页| 欧美在线国产精品| 国产97在线|亚洲| 91久久中文字幕| 91深夜福利视频| 欧美一级成年大片在线观看| 欧美专区在线观看| 91亚洲精华国产精华| 欧美在线视频在线播放完整版免费观看| 日韩在线观看你懂的| 一本一道久久a久久精品逆3p| 日韩美女在线观看一区| 亚洲va国产va天堂va久久| 国产精品久久久久久久久久久新郎| 国产精品久久久久久久久久免费| 91在线观看免费高清| 亚洲国产私拍精品国模在线观看| 国产日韩换脸av一区在线观看| 欧美成人午夜激情在线| 亚洲免费伊人电影在线观看av| 日韩av一区在线| 国产激情视频一区| 日韩成人在线网站| 精品人伦一区二区三区蜜桃免费| 国产九九精品视频| 国产丝袜高跟一区| 亚洲图片在区色| 亚洲欧美一区二区三区情侣bbw| 日本在线观看天堂男亚洲| 国产精品麻豆va在线播放|