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

定義

在JS里薪韩,有一些事件是很容易頻繁觸發(fā)的确沸,比如窗口的resize、scroll俘陷、鼠標(biāo)的onmousemove等操作罗捎,在事件頻繁觸發(fā)的過程中,不可避免的導(dǎo)致頻繁執(zhí)行觸發(fā)事件中的函數(shù)拉盾。為了防止這種情況的發(fā)生桨菜,主流的解決方案有兩種,防抖(debounce)和節(jié)流(throttle)

頻繁執(zhí)行情況

            var num = 1;
            var moveCntent = document.getElementById('example')
            function count(){
                moveCntent.innerHTML++;
            }
            moveCntent.onmousemove = count

效果如下:

image.png

可以明顯的看到捉偏,count 函數(shù)執(zhí)行的非常頻繁倒得,假如現(xiàn)在我們count函數(shù)里執(zhí)行的是一個Ajax請求,那么問題就會非常嚴重了告私。

防抖

函數(shù)防抖就是在一段時間(n毫秒)觸發(fā)或調(diào)用函數(shù)時,只執(zhí)行一次; 也可以理解為觸發(fā)n毫秒之后才會調(diào)用一次屎暇。

防抖函數(shù)的寫法主要有兩種,非立即執(zhí)行版本立即執(zhí)行版本驻粟。

非立即執(zhí)行版

                var num = 1;
                var moveCntent = document.getElementById('example')
                function count(){
                        moveCntent.innerHTML++;
                }
                moveCntent .onmousemove = count
                function debounce(fn,delay){
                        var timer;
                        return function(){
                            var _this = this;
                            var args = arguments;
                            if(timer) clearTimeout(timeout);
                            timer = setTimeout(function(){
                                fn.apply(_this,args)
                            },delay)
                            }
                    }
                moveCntent.onmousemove = debounce(count,1000)

原理是維護一個計時器,規(guī)定在delay時間后觸發(fā)函數(shù)蜀撑,但是在delay時間內(nèi)再次觸發(fā)的話挤巡,就會取消之前的計時器而重新設(shè)置酷麦。這樣一來,只有最后一次操作能被觸發(fā)沃饶。

效果如下:

image

在觸發(fā)事件1秒后才執(zhí)行,如果在觸發(fā)事件的一秒內(nèi)又觸發(fā)了事件糊肤,則重新計算函數(shù)執(zhí)行時間

立即執(zhí)行版

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

立即執(zhí)行版本和非例行版本的區(qū)別是:

  • 立即執(zhí)行版本:觸發(fā)事件后函數(shù)立即執(zhí)行琴昆,然后n秒內(nèi)不觸發(fā)時間才會繼續(xù)執(zhí)行
  • 非立即執(zhí)行版本:觸發(fā)事件后函數(shù)不會立即執(zhí)行馆揉,而是在n秒回才會執(zhí)行

節(jié)流

函數(shù)節(jié)流,就是指連續(xù)觸發(fā)的事件在n秒鐘只執(zhí)行一次函數(shù)。降低函數(shù)的執(zhí)行頻率舷暮,對于函數(shù)節(jié)流,通常也也有兩種方式實現(xiàn)下面,分別是時間戳版定時器版

時間戳版

                function throttle(fn,delay){
                    var previous = 0;
                    return function(){
                        var now = Date.now();
                        var _this = this;
                        var args = arguments;
                        if(now - previous > delay){
                            fn.apply(_this,args);
                            previous = now;
                        }
                    };
                }
                moveCntent.onmousemove = throttle(count,1000)

當(dāng)高頻事件觸發(fā)時,第一次會立即執(zhí)行诸狭,而后再怎么頻繁地觸發(fā)事件券膀,也都是每delay時間才執(zhí)行一次驯遇。

效果如下:

image

持續(xù)觸發(fā)事件的過程中,函數(shù)會立即執(zhí)行叉庐,并且每一秒執(zhí)行一次

定時器版

                function throttle(fn,delay){
                    var timer;
                    return function(){
                        var _this = this;
                        var args = arguments;
                        if(!timer){
                            timer = setTimeout(function(){
                                timer = null;
                                fn.apply(_this,args);
                            },delay);
                        }
                    };
                }

在持續(xù)觸發(fā)事件的過程中,函數(shù)不會立即執(zhí)行陡叠,并且每一秒執(zhí)行一次玩郊,停止觸發(fā)事件后枉阵,還會再執(zhí)行一次

效果如下:

image

時間戳版本和定時器版本的區(qū)別是:

  • 時間戳版本:觸發(fā)事件后函數(shù)立即執(zhí)行译红,每n秒執(zhí)行一次
  • 定時器版本:觸發(fā)事件后函數(shù)不會立即執(zhí)行,每n秒執(zhí)行一次兴溜,停止觸發(fā)后還會執(zhí)行一次

總結(jié)

函數(shù)防抖:將幾次操作合并為一此操作進行侦厚。原理是維護一個計時器,規(guī)定在delay時間后觸發(fā)函數(shù)拙徽,但是在delay時間內(nèi)再次觸發(fā)的話刨沦,就會取消之前的計時器而重新設(shè)置。這樣一來膘怕,只有最后一次操作能被觸發(fā)想诅。

函數(shù)節(jié)流:使得一定時間內(nèi)只觸發(fā)一次函數(shù)。原理是通過判斷是否到達一定時間來觸發(fā)函數(shù)岛心。

區(qū)別: 函數(shù)節(jié)流不管事件觸發(fā)有多頻繁来破,都會保證在規(guī)定時間內(nèi)一定會執(zhí)行一次真正的事件處理函數(shù),而函數(shù)防抖只是在最后一次事件后才觸發(fā)一次函數(shù)忘古。 比如在頁面的無限加載場景下徘禁,我們需要用戶在滾動頁面時,每隔一段時間發(fā)一次 Ajax 請求存皂,而不是在用戶停下滾動頁面操作時才去請求數(shù)據(jù)。這樣的場景,就適合用節(jié)流技術(shù)來實現(xiàn)旦袋。

轉(zhuǎn)自 http://www.reibang.com/p/35e6ed1642e4

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末骤菠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子疤孕,更是在濱河造成了極大的恐慌商乎,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祭阀,死亡現(xiàn)場離奇詭異鹉戚,居然都是意外死亡,警方通過查閱死者的電腦和手機专控,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進店門抹凳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人伦腐,你說我怎么就攤上這事赢底。” “怎么了柏蘑?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵幸冻,是天一觀的道長。 經(jīng)常有香客問我咳焚,道長洽损,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任革半,我火速辦了婚禮碑定,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘督惰。我一直安慰自己不傅,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布赏胚。 她就那樣靜靜地躺著访娶,像睡著了一般觉阅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上典勇,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天,我揣著相機與錄音权烧,去河邊找鬼眯亦。 笑死妻率,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宫静。 我是一名探鬼主播,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼孤里,長吁一口氣:“原來是場噩夢啊……” “哼橘洞!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起震檩,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎博其,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體慕淡,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡沸毁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了携兵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡徐紧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出并级,到底是詐尸還是另有隱情,我是刑警寧澤嘲碧,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布父阻,位于F島的核電站望抽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏糠聪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望趣惠。 院中可真熱鬧,春花似錦味悄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽费韭。三九已至,卻和暖如春星持,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背督暂。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工穷吮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捡鱼。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像堰汉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子翘鸭,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,922評論 2 361