前端效能最佳化|什麼是防抖和節流?
防抖與節流、節流與防抖,是不是經常讓你不知道誰是誰。
乘電梯,如果有人進入電梯(觸發事件),電梯門會等待 5 秒再關閉,在等待期間如果又有人按電梯進入(在 5 秒內再次觸發該事件),電梯門又要重新等待 5 秒,直到最後一個人進入電梯,電梯門在等待 5 秒後關閉。
這就是我們生活中遇見的防抖,那節流是什麼呢?
打過遊戲的朋友都知道,遊戲當中技能的使用是有冷卻時間的,就算你不停地按技能,也只能在規定時間內觸發一次,這就是節流。防抖和節流是前端最佳化經常遇見的知識點,快拿好小板凳和我一起開啟接下來的學習吧!
函式防抖(debounce)
1、原理
當持續觸發事件時,在規定的時間內該事件沒有被再次呼叫,事件處理函式就會執行一次,如果在規定時間內事件再次被呼叫,就重新開始計時。
2、使用場景
按鈕提交場景:防止多次提交按鈕,只執行最後提交的一次。
搜尋框的聯想詞:只傳送最後一次輸入結果的請求。
進行視窗的 resize、scroll 事件時: 只計算最後一次結果進行執行。
輸入框內容的校驗:只進行最後一次輸入的內容校驗。
function debounce(func, wait, immediate) {
let timer;
let debounced = function () {
let _this = this;
let args = arguments;
clearTimeout(timer);
if (immediate) {
let executeNow = !timer;
timer = setTimeout(function () {
timer = null;
}, wait);
if (executeNow) {
func.apply(_this, args);
}
} else {
timer = setTimeout(function () {
func.apply(_this, args)
}, wait);
}
debounced.cancel = function () {
clearTimeout(timer);
timer = null;
}
}
return debounced;
}
3、實現
用 immediate 引數控制函式是否立即執行。如果函式是立即執行的,就立即呼叫;如果函式是延遲執行的,就快取上下文和引數,放到延遲函式中去執行。一旦開始一個定時器,只要定時器還在,每次觸發函式都會重新計時。一旦事件不觸發了,定時器時間到,執行一次事件函式,定時器重置為 null,就可以再次點選了。
函式節流(throttle)
1、原理
當持續觸發事件時,保證在規定的時間內呼叫一次事件處理函式。如果這個單位時間內觸發多次函式,只有一次有效。
2、使用場景
DOM 元素的拖拽功能實現: 一個時間週期去獲取一次位置並計算,防止超高頻次觸發位置變動。
進行視窗的 resize、scorll 事件時: 只計算最後一次結果進行執行。
3、實現
**時間戳方式:**當觸發事件的時候,我們取出當前的時間戳,然後減去之前的時間戳,如果大於設定的時間週期,就執行函式,然後更新時間戳為當前的時間戳;如果小於,就不執行。該方式第一次事件立即執行,最後一次事件不執行。
function throttle(func,wait){
let _this,args;
let preTime = 0;
return function(){
_this = this;
args = arguments;
let now = new Date().valueOf();
if(now-preTime > wait){
func.apply(_this,args);
preTime = now;
}
}
}
**定時器方式:**當觸發事件的時候,我們設定一個定時器,再觸發事件的時候,如果定時器存在,就不執行,直到定時器執行完,然後執行函式,清空定時器,這樣就可以設定下個定時器。該方式第一次事件不立即執行,最後一次事件執行。
function throttle(func,wait){
let _this, args, timer;
return function(){
_this = this;
args = arguments;
if(!timer){
timer = setTimeout(() => {
timer = null;
func.apply(_this,args);
},wait);
}
}
}
**時間戳 + 定時器方式: **用函式引數實現配置項(leading:boolean、trailing:boolean),控制事件第一次是否立即觸發和事件最後一次是否觸發。
function throttle(func,wait,options){
let _this, args, timer;
let preTime = 0;
if(!options) options = {};
return function(){
_this = this;
args = arguments;
let now = new Date().valueOf();
if(options.leading === false && !preTime) {
preTime = now;
}
if((now - preTime) > wait){
if(timer){
clearTimeout(timer);
timer = null;
}
func.apply(_this,args);
preTime = now;
} else if(!timer && options.trailing !== false){
timer = setTimeout(() => {
preTime = new Date().valueOf;
timer = null;
func.apply(_this,args);
},wait);
}
}
}
總結
函式防抖:
將幾次操作合併為一次操作進行。原理是維護一個計時器,規定在 delay 時間後觸發函式,但是在 delay 時間內再次觸發的話,就會取消之前的計時器而重新設定。這樣一來,只有最後一次操作能被觸發。
函式節流:
使得一定時間內只觸發一次函式。原理是透過判斷是否到達一定時間來觸發函式。
兩者的區別:
函式節流不管事件觸發有多頻繁,都會保證在規定時間內一定會執行一次事件處理函式,而函式防抖只是在最後一次事件後才觸發一次函式。
作者
林茂
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/430/viewspace-2806993/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 前端效能最佳化---防抖與節流--02前端
- 效能優化之防抖和節流優化
- 防抖和節流
- js防抖和節流JS
- 前端效能優化-圖片懶載入(防抖、節流)前端優化
- 函式節流和防抖函式
- 防抖和節流原理分析
- 函式防抖和節流函式
- 防抖節流
- 前端戰五渣學JavaScript——防抖、節流和rAF前端JavaScript
- 前端都應該要掌握的防抖和節流前端
- js 函式防抖和節流JS函式
- 函式的防抖和節流函式
- js防抖 和節流函式JS函式
- 前端面試查漏補缺--(一) 防抖和節流前端面試
- 節流與防抖
- 防抖與節流
- UnderScore原始碼看防抖和節流原始碼
- 函式防抖和函式節流函式
- JavaScript專題系列-防抖和節流JavaScript
- 固定表頭和首列,防抖節流
- 防抖和節流(例項講解)
- debounce(防抖) & throttle(節流)
- 節流防抖封裝封裝
- 防抖動處理和節流 小技巧
- JS函式節流和函式防抖JS函式
- js函式中的節流和防抖JS函式
- 蝦扯蛋之函式防抖和節流函式
- JS簡單實現防抖和節流JS
- js函式防抖debounce和節流throttleJS函式
- JavaScript之節流與防抖JavaScript
- 筆記-JavaScript[節流][防抖]筆記JavaScript
- JavaScript淺析 -- 定時器和節流防抖JavaScript定時器
- 【js】什麼是函式節流與函式去抖JS函式
- 當Flutter遇到節流與防抖Flutter
- 函式的防抖與節流函式
- JavaScript中函式防抖、節流JavaScript函式
- js優化之防抖節流JS優化