成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

函數(shù)防抖與函數(shù)節(jié)流

n7then / 2525人閱讀

摘要:適用情景對象的事件拖拽時的事件射擊游戲中的事件文字輸入自動完成的事件實際上對于的事件,實際需求大多為停止改變大小毫秒后執(zhí)行后續(xù)處理防抖而其他事件大多的需求是以一定的頻率執(zhí)行后續(xù)處理節(jié)流。

區(qū)別

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

throttle(節(jié)流):預(yù)先設(shè)定一個執(zhí)行周期,當(dāng)調(diào)用動作的時刻大于等于執(zhí)行周期則執(zhí)行該動作,然后進(jìn)入下一個新周期。比如:將水龍頭擰緊直到水是以水滴的形式流出,那你會發(fā)現(xiàn)每隔一段時間,就會有一滴水流出。

適用情景

window對象的resize、scroll事件

拖拽時的mousemove事件

射擊游戲中的mousedown、keydown事件

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

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

增加一個輔助函數(shù) restArgs

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

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

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

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, 意味之前嘗試調(diào)用過func
            // 由于debounce只認(rèn)最新的一次調(diào)用, 所以之前等待執(zhí)行的func都會被終止
            if (timeout) clearTimeout(timeout);
            // 如果允許新的調(diào)用嘗試立即執(zhí)行,
            if (immediate) {
                // 如果之前尚沒有調(diào)用嘗試,那么此次調(diào)用可以立馬執(zhí)行,否則一定得等待之前的執(zhí)行完畢
                var callNow = !timeout;
                // 刷新timeout
                timeout = setTimeout(later, wait);
                // 如果能被立即執(zhí)行,立即執(zhí)行
                if (callNow) result = func.apply(this, args);
            } else {
                // 否則,這次嘗試調(diào)用會延時wait個時間
                timeout = delay(later, wait, this, args);
            }

            return result;
        });

        debounced.cancel = function () {
            clearTimeout(timeout);
            timeout = null;
        };

        return debounced;
    };
throttle

創(chuàng)建并返回一個像節(jié)流閥一樣的函數(shù),當(dāng)重復(fù)調(diào)用函數(shù)的時候,至少每隔 wait毫秒調(diào)用一次該函數(shù)。對于想控制一些觸發(fā)頻率較高的事件有幫助。

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

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

        var timeout, context, args, result;
        // 最近一次func被調(diào)用的時間點
        var previous = 0;
        if (!options) options = {};

        // 創(chuàng)建一個延后執(zhí)行的函數(shù)包裹住func的執(zhí)行過程
        var later = function () {
            // 執(zhí)行時,刷新最近一次調(diào)用時間
            previous = options.leading === false ? 0 : new Date();
            // 清空定時器
            timeout = null;
            result = func.apply(context, args);
            if (!timeout) context = args = null;
        };

        // 返回一個throttled的函數(shù)
        var throttled = function () {
            // ----- 節(jié)流函數(shù)開始執(zhí)行----
            // 我們嘗試調(diào)用func時,會首先記錄當(dāng)前時間戳
            var now = new Date();
            // 是否是第一次調(diào)用
            if (!previous && options.leading === false) previous = now;
            // func還要等待多久才能被調(diào)用 =  預(yù)設(shè)的最小等待期-(當(dāng)前時間-上一次調(diào)用的時間)
            // 顯然,如果第一次調(diào)用,且未設(shè)置options.leading = false,那么remaing=0,func會被立即執(zhí)行
            var remaining = wait - (now - previous);
            // 記錄之后執(zhí)行時需要的上下文和參數(shù)
            context = this;
            args = arguments;

            // 如果計算后能被立即執(zhí)行
            if (remaining <= 0 || remaining > wait) {
                // 清除之前的“最新調(diào)用”
                if (timeout) {
                    clearTimeout(timeout);
                    timeout = null;
                }
                // 刷新最近一次func調(diào)用的時間點
                previous = now;
                // 執(zhí)行func調(diào)用
                result = func.apply(context, args);
                // 如果timeout被清空了,
                if (!timeout) context = args = null;

            } else if (!timeout && options.trailing !== false) {
                // 如果設(shè)置了trailing edge,那么暫緩此次調(diào)用嘗試的執(zhí)行
                timeout = setTimeout(later, remaining);
            }
            return result;
        };

        // 可以取消函數(shù)的節(jié)流化
        throttled.cancel = function () {
            clearTimeout(timeout);
            previous = 0;
            timeout = context = args = null;
        };

        return throttled;
    };

點擊查看demo

參考文章
http://www.tuicool.com/articl...
http://blog.csdn.net/jinboker...
http://www.css88.com/doc/unde...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/81429.html

相關(guān)文章

  • 小菊花課堂之JS的抖與節(jié)流

    摘要:文章來源詳談防抖和節(jié)流輕松理解函數(shù)節(jié)流和函數(shù)防抖函數(shù)防抖和節(jié)流好啦,今天的小菊花課堂之的防抖與節(jié)流的內(nèi)容就告一段落啦,感各位能耐心看到這里。 前言 陸游有一首《冬夜讀書示子聿》——古人學(xué)問無遺力,少壯工夫老始成。紙上得來終覺淺,絕知此事要躬行。,其中的意思想必大家都能明白,在學(xué)習(xí)或工作中,不斷的印證著這首詩的內(nèi)涵。所以,又有了此篇小菊花文章。 詳解 在前端開發(fā)中,我們經(jīng)常會碰到一些會持...

    leoperfect 評論0 收藏0
  • 小菊花課堂之JS的抖與節(jié)流

    摘要:文章來源詳談防抖和節(jié)流輕松理解函數(shù)節(jié)流和函數(shù)防抖函數(shù)防抖和節(jié)流好啦,今天的小菊花課堂之的防抖與節(jié)流的內(nèi)容就告一段落啦,感各位能耐心看到這里。 前言 陸游有一首《冬夜讀書示子聿》——古人學(xué)問無遺力,少壯工夫老始成。紙上得來終覺淺,絕知此事要躬行。,其中的意思想必大家都能明白,在學(xué)習(xí)或工作中,不斷的印證著這首詩的內(nèi)涵。所以,又有了此篇小菊花文章。 詳解 在前端開發(fā)中,我們經(jīng)常會碰到一些會持...

    Yangder 評論0 收藏0
  • JavaScript:函數(shù)抖與函數(shù)節(jié)流

    摘要:函數(shù)防抖簡單實現(xiàn)模擬請求獲取函數(shù)的作用域和變量清除定時器節(jié)流名詞解釋連續(xù)執(zhí)行函數(shù),每隔一定時間執(zhí)行函數(shù)。效果函數(shù)防抖是某一段時間內(nèi)只執(zhí)行一次函數(shù)節(jié)流是間隔時間執(zhí)行,不管事件觸發(fā)有多頻繁,都會保證在規(guī)定時間內(nèi)一定會執(zhí)行一次真正的事件處理函數(shù)。 防抖(debounce) 名詞解釋:在事件被觸發(fā)n秒后再執(zhí)行回調(diào)函數(shù),如果在這n秒內(nèi)又被觸發(fā),則重新計時。 使用場景:以百度輸入框例,比如你要查詢...

    elina 評論0 收藏0
  • 高級函數(shù)技巧-函數(shù)抖與節(jié)流

    摘要:封裝方法也比較簡單,書中對此問題也進(jìn)行了處理使用定時器,讓函數(shù)延遲秒后執(zhí)行,在此秒內(nèi),然后函數(shù)再次被調(diào)用,則刪除上次的定時器,取消上次調(diào)用的隊列任務(wù),重新設(shè)置定時器。 在實際開發(fā)中,函數(shù)一定是最實用最頻繁的一部分,無論是以函數(shù)為核心的函數(shù)式編程,還是更多人選擇的面向?qū)ο笫降木幊蹋紩泻瘮?shù)的身影,所以對函數(shù)進(jìn)行深入的研究是非常有必要的。 函數(shù)節(jié)流 比較直白的說,函數(shù)節(jié)流就是強(qiáng)制規(guī)定一...

    whinc 評論0 收藏0
  • 前端進(jìn)擊的巨人(八):淺談函數(shù)抖與節(jié)流

    摘要:隆重請出主角防抖與節(jié)流。防抖與節(jié)流的異同相同都是防止某一時間段內(nèi),函數(shù)被頻繁調(diào)用執(zhí)行,通過時間頻率控制,減少回調(diào)函數(shù)執(zhí)行次數(shù),來實現(xiàn)相關(guān)性能優(yōu)化。參考文章分鐘理解的節(jié)流防抖及使用場景函數(shù)防抖和節(jié)流 showImg(https://segmentfault.com/img/bVburM8?w=800&h=600); 本篇課題,或許早已是爛大街的解讀文章。不過春招系列面試下來,不少伙伴們還...

    _Zhao 評論0 收藏0
  • 抖與節(jié)流(源碼學(xué)習(xí))

    摘要:防抖與節(jié)流源碼學(xué)習(xí)最近自己擼了一個輪播圖,在點擊切換的時候,為了尋求更好的用戶體驗,引入了節(jié)流,在此記錄對源碼的學(xué)習(xí)過程源碼來源防抖函數(shù)防抖使用場景現(xiàn)在我們需要做一個搜索框,當(dāng)用戶輸入文字,執(zhí)行事件的時候,需要發(fā)出異步請求去進(jìn)行結(jié)果查詢。 防抖與節(jié)流(源碼學(xué)習(xí)) 最近自己擼了一個輪播圖,在點擊切換的時候,為了尋求更好的用戶體驗,引入了節(jié)流,在此記錄對源碼的學(xué)習(xí)過程源碼來源:unders...

    instein 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<