亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術(shù)文章
文章詳情頁

Javascript節(jié)流函數(shù)throttle和防抖函數(shù)debounce

瀏覽:60日期:2023-10-06 16:23:44

問題的引出

在一些場景往往由于事件頻繁被觸發(fā),因而頻繁地進(jìn)行DOM操作、資源加載,導(dǎo)致UI停頓甚至瀏覽器崩潰。

在這樣的情況下,我們實際上的需求大多為停止改變大小n毫秒后執(zhí)行后續(xù)處理;而其他事件大多的需求是以一定的頻率執(zhí)行后續(xù)處理。針對這兩種需求就出現(xiàn)了debounce和throttle兩種解決辦法。

1. resize事件

2. mousemove事件

3. touchmove事件

4.scroll事件

throttle 與 debounce

在現(xiàn)在很多的javascript框架中都提供了這兩個函數(shù)。例如 jquery中有throttle和debounce插件, underscore.js ,Lodash.js 等都提供了這兩個函數(shù)。

原理:

首先我們會想到設(shè)置一定的時間范圍delay,每隔delayms 執(zhí)行不超過一次。

事件處理函數(shù)什么時候執(zhí)行能? 這里有兩個選擇,一是先執(zhí)行,再間隔delayms來等待;或者是先等待delayms,然后執(zhí)行事件處理函數(shù)。

操作過程中的事件全不管,反正只執(zhí)行一次事件處理。

相同低,這一次的事件處理可以是先執(zhí)行一次,然后后面的事件都不管; 或者前面的都不管,最后操作完了再執(zhí)行一次事件處理。

區(qū)別:

1. throttle

如果將水龍頭擰緊直到水是以水滴的形式流出,那你會發(fā)現(xiàn)每隔一段時間,就會有一滴水流出。

也就是會說預(yù)先設(shè)定一個執(zhí)行周期,當(dāng)調(diào)用動作的時刻大于等于執(zhí)行周期則執(zhí)行該動作,然后進(jìn)入下一個新周期。

2.debounce

如果用手指一直按住一個彈簧,它將不會彈起直到你松手為止。

也就是說當(dāng)調(diào)用動作n毫秒后,才會執(zhí)行該動作,若在這n毫秒內(nèi)又調(diào)用此動作則將重新計算執(zhí)行時間。

簡單代碼實現(xiàn)及實驗結(jié)果

那么下面我們自己簡單地實現(xiàn)下這兩個函數(shù):

throttle 函數(shù):

window.addEventListener('resize', throttle(callback, 300, {leading:false})); window.addEventListener('resize', callback2); function callback () { console.count('Throttled'); } function callback2 () { console.count('Not Throttled'); } /** * 頻率控制函數(shù), fn執(zhí)行次數(shù)不超過 1 次/delay * @param fn{Function} 傳入的函數(shù) * @param delay{Number} 時間間隔 * @param options{Object} 如果想忽略開始邊界上的調(diào)用則傳入 {leading:false}, * 如果想忽略結(jié)束邊界上的調(diào)用則傳入 {trailing:false}, * @returns {Function} 返回調(diào)用函數(shù) */ function throttle(fn,delay,options) { var wait=false; if (!options) options = {}; return function(){ var that = this,args=arguments; if(!wait){ if (!(options.leading === false)){ fn.apply(that,args); } wait=true; setTimeout(function () { if (!(options.trailing === false)){ fn.apply(that,args); } wait=false; },delay); } } }

將以上代碼貼入瀏覽器中運行,可得到:

Javascript節(jié)流函數(shù)throttle和防抖函數(shù)debounce

下面再看debounce函數(shù)的情況,

debounce 函數(shù):

window.addEventListener('resize', throttle(callback, 300, {leading:false}));window.addEventListener('resize', callback2);function callback () { console.count('Throttled'); }function callback2 () { console.count('Not Throttled'); }/** * 空閑控制函數(shù), fn僅執(zhí)行一次 * @param fn{Function} 傳入的函數(shù) * @param delay{Number} 時間間隔 * @param options{Object} 如果想忽略開始邊界上的調(diào)用則傳入 {leading:false}, * 如果想忽略結(jié)束邊界上的調(diào)用則傳入 {trailing:false}, * @returns {Function} 返回調(diào)用函數(shù) */function debounce(fn, delay, options) { var timeoutId; if (!options) options = {}; var leadingExc = false; return function() { var that = this, args = arguments; if (!leadingExc&&!(options.leading === false)) { fn.apply(that, args); } leadingExc=true; if (timeoutId) { clearTimeout(timeoutId); } timeoutId = setTimeout(function() { if (!(options.trailing === false)) {fn.apply(that, args); } leadingExc=false; }, delay); }}

將以上代碼貼入瀏覽器中運行,分三次改變窗口大小,可看到,每一次改變窗口的大小都會把開始和結(jié)束邊界的事件處理函數(shù)各執(zhí)行一次:

Javascript節(jié)流函數(shù)throttle和防抖函數(shù)debounce

如果是一次性改變窗口大小,會發(fā)現(xiàn)開始和結(jié)束的邊界各執(zhí)行一次時間處理函數(shù),請注意與一次性改變窗口大小時 throttle 情況的對比:

Javascript節(jié)流函數(shù)throttle和防抖函數(shù)debounce

underscore.js 的代碼實現(xiàn)

_.throttle函數(shù)

/** * 頻率控制函數(shù), fn執(zhí)行次數(shù)不超過 1 次/delay * @param fn{Function} 傳入的函數(shù) * @param delay{Number} 時間間隔 * @param options{Object} 如果想忽略開始邊界上的調(diào)用則傳入 {leading:false}, * 如果想忽略結(jié)束邊界上的調(diào)用則傳入 {trailing:false}, * @returns {Function} 返回調(diào)用函數(shù) */_.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; var remaining = wait - (now - previous); context = this; args = arguments; 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; };};

_.debounce函數(shù)

/** * 空閑控制函數(shù), fn僅執(zhí)行一次 * @param fn{Function} 傳入的函數(shù) * @param delay{Number} 時間間隔 * @param options{Object} 如果想忽略開始邊界上的調(diào)用則傳入 {leading:false}, * 如果想忽略結(jié)束邊界上的調(diào)用則傳入 {trailing:false}, * @returns {Function} 返回調(diào)用函數(shù) */_.debounce = function(func, wait, immediate) { var timeout, args, context, timestamp, result; var later = function() { 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(); var callNow = immediate && !timeout; if (!timeout) timeout = setTimeout(later, wait); if (callNow) { result = func.apply(context, args); context = args = null; } return result; };};

參考的文章

Debounce and Throttle: a visual explanationjQuery throttle / debounce: Sometimes, less is more!underscore.js

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: JavaScript
相關(guān)文章:
主站蜘蛛池模板: 中国内地毛片免费高清 | 日本级毛片免费观看 | 41sao.can在线观看国产 | 国产精品揄拍100视频最近 | 国产三级久久久精品麻豆三级 | 好色婷婷 | 麻豆视传媒短视频网站 - | 亚洲欧洲一二三区机械有限公司 | 日本xxwwwxxxx18| 精品网址 | 色综合久| 欧美成人精品一区二三区在线观看 | 在浴室边摸边吃奶边做视频 | 一区二区手机视频 | 日韩中文字幕久久久经典网 | 国产制服丝袜在线 | 日本久久草 | 亚洲欧美久久婷婷爱综合一区天堂 | 欧美一区二区在线免费观看 | 久久国产乱子伦精品免费一 | 米奇精品一区二区三区在线观看 | 欧美另类偷自拍视频二区 | 国产区精品福利在线观看精品 | 黑人香蕉又粗又大视频免费 | 涩涩网站在线观看 | 久久国产经典 | 亚洲成人激情片 | 久久er热视频在这里精品 | 一级做a爰片性色毛片中国 一级做a爰片性色毛片男 | 日本久久久免费高清 | 年轻人www影视| 九九热视 | 亚洲 国产精品 日韩 | 做爰成人五级在线视频 | 成人无遮挡毛片免费看 | 鲁大师在线观看在线播放 | 免费影院在线 | 日韩色影院 | 成年片免费网址网站 | 99久久99 | 日韩在线视频不卡一区二区三区 |