JavaScript函數(shù)節(jié)流和函數(shù)去抖知識點(diǎn)學(xué)習(xí)
概念
節(jié)流 (throttle) 讓一個函數(shù)不要執(zhí)行的太頻繁,減少執(zhí)行過快的調(diào)用,叫節(jié)流
去抖 (debounce) 去抖就是對于一定時(shí)間段的連續(xù)的函數(shù)調(diào)用,只讓其執(zhí)行一次
throttle 應(yīng)用場景
- DOM 元素的拖拽功能實(shí)現(xiàn)(mousemove)
- 射擊游戲的 mousedown/keydown 事件(單位時(shí)間只能發(fā)射一顆子彈)
- 計(jì)算鼠標(biāo)移動的距離(mousemove)
- Canvas 模擬畫板功能(mousemove
- 搜索聯(lián)想(keyup
- 監(jiān)聽滾動事件判斷是否到頁面底部自動加載更多:給 scroll 加了 debounce 后,只有用戶停止?jié)L動后,才會判斷是否到了頁面底部;如果是 throttle 的話,只要頁面滾動就會間隔一段時(shí)間判斷一次
debounce 應(yīng)用場景
每次 resize/scroll 觸發(fā)統(tǒng)計(jì)事件
文本輸入的驗(yàn)證(連續(xù)輸入文字后發(fā)送 AJAX 請求進(jìn)行驗(yàn)證,驗(yàn)證一次就好)
函數(shù)去抖的實(shí)現(xiàn)
我們以scroll事件為例,探究如何是實(shí)現(xiàn)滾動一次窗口打印一個hello world 字符串。 如果不對其節(jié)流或者去抖:
window.onscroll = function () {
console.log('hello world');
}
這樣每滾動一次,實(shí)際上會打印多個 hello world。 函數(shù)去抖背后的思路是指,某些代碼不可能在沒有間斷的情況下連續(xù)執(zhí)行。創(chuàng)建一個定時(shí)器,在指定的時(shí)間間隔之后運(yùn)行代碼。當(dāng)?shù)诙握{(diào)用該函數(shù)時(shí),它會清除前一次的定時(shí)器并設(shè)置另一個。如果前一個定時(shí)器已經(jīng)執(zhí)行過了,這個操作就沒有任何意義。然而,如果前一個定時(shí)器尚未執(zhí)行,其實(shí)就是將其替換為一個新的定時(shí)器。目的是只有在執(zhí)行函數(shù)的請求停止了一段時(shí)間之后才執(zhí)行。
《高程三》給出了最簡潔最經(jīng)典的去抖代碼,如下:
function debounce(method, context) {
clearTimeout(method.tId);
method.tId = setTimeout(function() {
method.call(context);
}, 1000);
}
function print() {
console.log('hello world');
}
window.onscroll = function() {
debounce(print);
};
再做一些改動
function debounce(delay, action) {
var tId;
return function () {
var context = this;
var arg = arguments;
if (tId) clearTimeout(tId);
tId = setTimeout(function () {
action.apply(context, arg);
}, delay);
}
}
window.onscroll = debounce(1000, print);
函數(shù)節(jié)流的實(shí)現(xiàn)
函數(shù)節(jié)流就是讓連續(xù)執(zhí)行的函數(shù),變?yōu)楣潭〞r(shí)間段間斷地執(zhí)行。 大概有兩種方式實(shí)現(xiàn)。
其一使用時(shí)間戳來判斷是否已經(jīng)到回調(diào)執(zhí)行時(shí)間,記錄上次執(zhí)行的時(shí)間戳,然后每次觸發(fā)事件時(shí)執(zhí)行回調(diào),回調(diào)中判斷當(dāng)前時(shí)間戳距離上次執(zhí)行時(shí)間戳的時(shí)間間隔是否有*s,如果是,則執(zhí)行,并更新上次執(zhí)行的時(shí)間戳,如此循環(huán)。
var throttle = function(delay, action) {
var last = 0;
return function() {
var curr = new Date();
if (curr - last > delay) {
action.apply(this, arguments);
last = curr;
}
}
}
第二種方法是使用定時(shí)器,比如,當(dāng)scroll事件剛觸發(fā)時(shí),打印一個hello world ,然后設(shè)置一個1000ms的定時(shí)器,此后每次觸發(fā)scroll事件,觸發(fā)回調(diào),如果已經(jīng)存在定時(shí)器,則回調(diào)不執(zhí)行方法,知道定時(shí)器出發(fā),handler被清除,然后重新設(shè)置定時(shí)器。
var throttle = function(delay, action) {
var timeout;
var later = function () {
timeout = setTimeout(function(){
clearTimeout(timeout);
// 解除引用
timeout = null;
}, delay);
};
later();
if (!timeout) {
action.apply(this, arguments);
later();
}
}
更新方法:
function throttlePro(delay, action) {
var tId;
return function () {
var context = this;
var arg = arguments;
if (tId) return;
tId = setTimeout(function () {
action.apply(context, arg);
clearTimeout(tId);
// setTimeout 返回一個整數(shù),clearTimeout 之后,tId還是那個整數(shù),setInterval同樣如此
tId = null;
}, delay);
}
}
相關(guān)文章
簡單總結(jié)JavaScript中的String字符串類型
就像其他語言那樣,js中的字符串類型可以表示一串字符,由雙引號包住,這里簡單總結(jié)JavaScript中的String字符串類型的一些基礎(chǔ)知識2016-05-05
JavaScript對象內(nèi)置對象,值類型和引用類型講解
本文講述了JavaScript的一些對象,值的類型和引用類型的講解,詳細(xì)的使用圖文進(jìn)行說明歸納和整理2021-06-06
JavaScript中Array 對象相關(guān)的幾個方法
JavaScript中Array 對象相關(guān)的幾個方法...2006-12-12
解析JavaScript面向?qū)ο蟾拍钪械腛bject類型與作用域
這篇文章主要介紹了解析JavaScript面向?qū)ο蟾拍钪械囊妙愋团c作用域,文中重點(diǎn)講解了擴(kuò)充函數(shù)運(yùn)行作用域的需要的call和apply方法,朋友可以參考下2016-05-05
JavaScript Break 和 Continue區(qū)別教程
JavaScript Break 和 Continue區(qū)別教程...2007-04-04

