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

首頁 > 網站 > WEB開發 > 正文

js函數防抖與函數節流

2024-04-27 15:16:24
字體:
來源:轉載
供稿:網友

區別

debounce(防抖):當調用動作n毫秒后,才會執行該動作,若在這n毫秒內又調用此動作則將重新計算執行時間。比如:如果用手指一直按住一個彈簧,它將不會彈起直到你松手為止。

throttle(節流):預先設定一個執行周期,當調用動作的時刻大于等于執行周期則執行該動作,然后進入下一個新周期。比如:將水龍頭擰緊直到水是以水滴的形式流出,那你會發現每隔一段時間,就會有一滴水流出。

適用情景

window對象的resize、scroll事件

拖拽時的mousemove事件

射擊游戲中的mousedown、keydown事件

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

實際上對于window的resize事件,實際需求大多為停止改變大小n毫秒后執行后續處理 (防抖);而其他事件大多的需求是以一定的頻率執行后續處理(節流)。

增加一個輔助函數 restArgs

/**     * 類ES6 rest參數的實現,使某個函數具備支持rest參數的能力     * @param func 需要rest參數的函數     * @param startIndex 從哪里開始標識rest參數, 如果不傳遞, 默認最后一個參數為rest參數     * @returns {Function} 返回一個具有rest參數的函數     */    var restArgs = function (func, startIndex) {        // rest參數從哪里開始,如果沒有,則默認視函數最后一個參數為rest參數        // 注意, 函數對象的length屬性, 揭示了函數的參數個數        /*         ex: function add(a,b) {return a+b;}         console.log(add.length;) // 2         */r        startIndex = startIndex == null ? func.length - 1 : +startIndex;        // 返回一個支持rest參數的函數        return function () {            // 校正參數, 以免出現負值情況            var length = Math.max(arguments.length - startIndex, 0);            // 為rest參數開辟數組存放            var rest = Array(length);            // 假設參數從2個開始: func(a,b,*rest)            // 調用: func(1,2,3,4,5); 實際的調用是:func.call(this, 1,2, [3,4,5]);            for (var index = 0; index < length; index++) {                rest[index] = arguments[index + startIndex];            }            // 根據rest參數不同, 分情況調用函數, 需要注意的是, rest參數總是最后一個參數, 否則會有歧義            switch (startIndex) {                case 0:                    // call的參數一個個傳                    return func.call(this, rest);                case 1:                    return func.call(this, arguments[0], rest);                case 2:                    return func.call(this, arguments[0], arguments[1], rest);            }            // 如果不是上面三種情況, 而是更通用的(應該是作者寫著寫著發現這個switch case可能越寫越長, 就用了apply)            var args = Array(startIndex + 1);            // 先拿到前面參數            for (index = 0; index < startIndex; index++) {                args[index] = arguments[index];            }            // 拼接上剩余參數            args[startIndex] = rest;            return func.apply(this, args);        };    };

debounce

返回 function 函數的防反跳版本, 將延遲函數的執行(真正的執行)在函數最后一次調用時刻的 wait 毫秒之后. 對于必須在一些輸入(多是一些用戶操作)停止到達之后執行的行為有幫助。 例如: 渲染一個Markdown格式的評論預覽, 當窗口停止改變大小之后重新計算布局, 等等.

傳參 immediate 為 true, debounce會在 wait 時間間隔的開始調用這個函數 。在類似不小心點了提交按鈕兩下而提交了兩次的情況下很有用。

var debounce = function (func, wait, immediate) {        var timeout, result;        var later = function (context, args) {            timeout = null;            if (args) result = func.apply(context, args);        };        var debounced = restArgs(function (args) {            // 一旦存在timeout, 意味之前嘗試調用過func            // 由于debounce只認最新的一次調用, 所以之前等待執行的func都會被終止            if (timeout) clearTimeout(timeout);            // 如果允許新的調用嘗試立即執行,            if (immediate) {                // 如果之前尚沒有調用嘗試,那么此次調用可以立馬執行,否則一定得等待之前的執行完畢                var callNow = !timeout;                // 刷新timeout                timeout = setTimeout(later, wait);                // 如果能被立即執行,立即執行                if (callNow) result = func.apply(this, args);            } else {                // 否則,這次嘗試調用會延時wait個時間                timeout = delay(later, wait, this, args);            }            return result;        });        debounced.cancel = function () {            clearTimeout(timeout);            timeout = null;        };        return debounced;    };

throttle

創建并返回一個像節流閥一樣的函數,當重復調用函數的時候,至少每隔 wait毫秒調用一次該函數。對于想控制一些觸發頻率較高的事件有幫助。(愚人碼頭注:詳見:javascript函數的throttle和debounce,感謝 @澳利澳先生 的翻譯建議)

默認情況下,throttle將在你調用的第一時間盡快執行這個function,并且,如果你在wait周期內調用任意次數的函數,都將盡快的被覆蓋。如果你想禁用第一次首先執行的話,傳遞{leading: false},還有如果你想禁用最后一次執行的話,傳遞{trailing: false}。

var throttle = function (func, wait, options) {        var timeout, context, args, result;        // 最近一次func被調用的時間點        var PRevious = 0;        if (!options) options = {};        // 創建一個延后執行的函數包裹住func的執行過程        var later = function () {            // 執行時,刷新最近一次調用時間            previous = options.leading === false ? 0 : new Date();            // 清空定時器            timeout = null;            result = func.apply(context, args);            if (!timeout) context = args = null;        };        // 返回一個throttled的函數        var throttled = function () {            // ----- 節流函數開始執行----            // 我們嘗試調用func時,會首先記錄當前時間戳            var now = new Date();            // 是否是第一次調用            if (!previous && options.leading === false) previous = now;            // func還要等待多久才能被調用 =  預設的最小等待期-(當前時間-上一次調用的時間)            // 顯然,如果第一次調用,且未設置options.leading = false,那么remaing=0,func會被立即執行            var remaining = wait - (now - previous);            // 記錄之后執行時需要的上下文和參數            context = this;            args = arguments;            // 如果計算后能被立即執行            if (remaining <= 0 || remaining > wait) {                // 清除之前的“最新調用”                if (timeout) {                    clearTimeout(timeout);                    timeout = null;                }                // 刷新最近一次func調用的時間點                previous = now;                // 執行func調用                result = func.apply(context, args);                // 如果timeout被清空了,                if (!timeout) context = args = null;            } else if (!timeout && options.trailing !== false) {                // 如果設置了trailing edge,那么暫緩此次調用嘗試的執行                timeout = setTimeout(later, remaining);            }            return result;        };        // 可以取消函數的節流化        throttled.cancel = function () {            clearTimeout(timeout);            previous = 0;            timeout = context = args = null;        };        return throttled;    };


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久精品美女| 亚洲综合中文字幕在线观看| 国产精品日韩精品| 欧美日韩美女在线| 亚洲国产成人在线播放| 精品国产乱码久久久久酒店| 欧美激情一区二区三区高清视频| 一区二区国产精品视频| 日韩免费高清在线观看| 国产做受高潮69| 亚洲精品午夜精品| 日韩网站免费观看高清| 欧美国产欧美亚洲国产日韩mv天天看完整| 国产午夜精品全部视频播放| 欧美大片网站在线观看| 亚洲人成在线播放| 亚洲系列中文字幕| 成人在线小视频| 亚洲三级 欧美三级| 欧洲美女7788成人免费视频| 九九久久国产精品| 4p变态网欧美系列| 2025国产精品视频| 中文字幕精品一区久久久久| 欧美乱妇高清无乱码| 欧美视频一二三| 欧美日韩在线观看视频| 日韩高清电影免费观看完整版| 精品久久中文字幕久久av| 欧美日韩国产区| 亚洲成av人片在线观看香蕉| 国产一区av在线| 亚洲精品二三区| 91地址最新发布| 激情av一区二区| 91成人免费观看网站| 欧美亚洲一区在线| 久久久亚洲福利精品午夜| 91网在线免费观看| 麻豆精品精华液| 欧美在线欧美在线| 在线精品国产欧美| 国产丝袜一区视频在线观看| 国产精品福利网站| 日韩在线视频一区| 久久久久久久久久久成人| 全亚洲最色的网站在线观看| 久久亚洲影音av资源网| 热门国产精品亚洲第一区在线| 中文.日本.精品| 国产欧美日韩综合精品| 日本一区二区在线播放| 亚洲第一av在线| 2024亚洲男人天堂| 欧美伦理91i| 久久久久久久爱| 一本一本久久a久久精品牛牛影视| 人九九综合九九宗合| 欧美激情亚洲激情| 97视频人免费观看| 91理论片午午论夜理片久久| 国产在线观看精品一区二区三区| 国产精品久久久久久久久久久新郎| 亚洲伊人久久大香线蕉av| 国产69久久精品成人看| 激情av一区二区| 7777免费精品视频| 久久久精品视频在线观看| 国产精品久久久久影院日本| 欧美日韩国产精品一区二区三区四区| 亚洲免费中文字幕| 精品久久久久久久久中文字幕| 欧美另类交人妖| 国内外成人免费激情在线视频网站| 在线成人中文字幕| 8090理伦午夜在线电影| 亚洲毛片在线免费观看| 亚洲91精品在线观看| 亚洲成人av片在线观看| 国内免费精品永久在线视频| 91大神在线播放精品| 精品国产欧美一区二区三区成人| 亚洲人成电影网站色xx| 国产一区二区三区三区在线观看| 日韩免费在线免费观看| 久久久久久久久久久av| 久久91亚洲人成电影网站| 国产精品免费一区二区三区都可以| 美女久久久久久久久久久| 日韩精品在线观| 黄色精品在线看| 日韩小视频在线观看| 色婷婷亚洲mv天堂mv在影片| 亚洲国产一区自拍| 日韩欧美精品网站| 亚洲成人在线视频播放| 91精品国产自产在线老师啪| 国产精品视频播放| 久久影院中文字幕| 亚洲xxxxx| 欧美丰满少妇xxxxx| 成人午夜在线视频一区| 午夜精品蜜臀一区二区三区免费| 日本精品一区二区三区在线播放视频| 日韩经典一区二区三区| 琪琪第一精品导航| 热99精品只有里视频精品| 国产91精品视频在线观看| 久久综合88中文色鬼| 久久久91精品国产一区不卡| 日韩欧美一区二区在线| 91免费国产网站| 中文字幕在线国产精品| 久久久久久久久久av| 中文字幕一区二区精品| 88xx成人精品| 91国产在线精品| 日韩中文字幕免费视频| 国产一区视频在线播放| 亚洲欧美一区二区三区久久| 亚洲人在线观看| 欧美精品在线播放| 日韩成人激情在线| 不卡毛片在线看| 亚洲综合在线做性| 国产99久久精品一区二区永久免费| 91国产美女视频| 69**夜色精品国产69乱| 国产成人精品视频在线| 亚洲新中文字幕| 日本精品va在线观看| 午夜精品久久久久久久久久久久久| 久久久久久久久爱| 97在线看免费观看视频在线观看| 2019国产精品自在线拍国产不卡| 久久久www成人免费精品| 亚洲最大激情中文字幕| 超碰97人人做人人爱少妇| 91手机视频在线观看| 亚洲免费人成在线视频观看| 国产免费一区二区三区在线观看| 欧美视频在线观看免费网址| 亚洲视频电影图片偷拍一区| 欧美一区二区三区精品电影| 91社区国产高清| 国产成人精品视| 欧美黑人xxxx| 欧美高清理论片| 亚洲国产天堂久久国产91| 国产精品mp4| 欧美成人免费小视频| 一本色道久久综合狠狠躁篇的优点| 国产精品永久免费在线| 亚洲精品久久久一区二区三区| 亚洲欧美成人在线| 国产一区在线播放| 成人久久一区二区三区| 欧美激情亚洲综合一区| 亚洲一区二区三区香蕉| 国产91露脸中文字幕在线| 免费97视频在线精品国自产拍| 久久这里有精品视频| 国产精品视频区| 国产亚洲人成网站在线观看|