函數(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

效果如下:



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

防抖

函數(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)

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

效果如下:



在觸發(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í)行一次。

效果如下:



持續(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í)行一次

效果如下:



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

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

總結(jié)

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

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容