?? 前言
- 前段時間群友說面試的時候老是分不清
防抖和節流, - 其實
防抖和節流不僅僅在面試中會讓大家手寫,在實際專案中也可以起到性能優化的作用,所以還是很有必要掌握的, - 接下來我就用一杯茶的時間帶大家徹底學會手寫
防抖和節流,
🍀 防抖
🌰 舉個例子
- 我們先拋開概念不談,其實在生活中也有很多
防抖的例子:- 比如你現在使用的電腦,在不使用后一段時間自動休眠
- 當你再次使用的時候重新激活,并開始你設定的時間倒計時
10分鐘 - 在這
10分鐘內你繼續使用電腦又會重新開始倒計時10分鐘 - 當你最后一次使用電腦并離開時重新倒計時
10分鐘過去了,電腦就休眠了

- 這其實這就是防抖的基本概念了~說白了就是在一段時間只執行一次,也就是我們上面的電腦只打開這一次,
- 我們上面的使用電腦可以理解為
觸發事件,而與我上面標注的setTimeout和clearTimeout其實就是防抖的主要要素了, - 當然上面的是生活中的例子,那我們在我們的日常開發中其實也經常用到,比如我們調整頁面的大小,驗證表單某個欄位是否重復時發生請求次數控制,防止表單多次提交等,
?? 手寫防抖
- 說了這么多,相信大家大概理解了
防抖的概念,那我們現在來實作一個防抖吧,假設我們要點擊一個按鈕新增一條資訊,當然我們不希望每次點擊都呼叫介面新增,我們希望多次點擊只新增一次,這時候我們該怎么寫呢?

- 首先我們先簡單的模擬一個按鈕被點擊的程序,
// debounce.js
let addBtn=document.getElementById('add')
function addOne(){
console.log('增加一個')
}
addBtn.addEventListener('click',addOne)
- 因為我們需要對執行的事件進行處理所以接下來我們需要封裝一下
addOne函式,
// debounce.js
let addBtn=document.getElementById('add')
function addOne(){
console.log('增加一個')
}
function debounce(fun){
return function(){
fun()
}
}
addBtn.addEventListener('click',debounce(addOne))
- 上面我們用閉包處理了一下
addOne函式,接下來我們需要添加一個延時器setTimeout來倒計時,當我們點擊按鈕后過2s再執行,
// debounce.js
function debounce(fun,time){
return function(){
setTimeout(()=>{
fun()
},time)
}
}
addBtn.addEventListener('click',debounce(addOne,2000))
- 現在延時的目的是達到了但是每次點擊都會新增一個新的
setTimeout而且并不能達到我們多次點擊只執行一次的效果, - 這時候就需要
clearTimeout登場了,我們需要在我們點擊了按鈕后也就是debounce執行時要先把之前的setTimeout先清除再重新計時,
function debounce(fun,time){
let timer
return function(){
clearTimeout(timer)
timer=setTimeout(()=>{
fun()
},time)
}
}
- 現在我們的一個防抖功能就完成了,但是這還沒完,如果我們在
addOne()列印this會發現我們這樣執行的this是指向Window的, - 這當然不是我們所希望的,我們需要使用
apply來改變this指向,再者就是我們需要考慮到執行函式的引數,因為不同的函式肯定會有不同的引數傳入,對于引數我們可以使用arguments處理,
function debounce(fun,time){
let timer
return function(){
clearTimeout(timer)
let args = arguments
timer=setTimeout(()=>{
fun.apply(this,args)
},time)
}
}
- 這樣我們的
防抖函式就手寫完成了,看起來其實也并不難,
- 總而言之
防抖就是在不斷的操作中(輸入、點擊等)最終只執行一次的一種提高性能的方法,
🍁 節流
🌰 舉個例子
- 當然我們生活中也會有很多節流的的例子,不知道大家有沒有留意過公園的灑水機:
- 一般我們會給灑水機設定一個時間假設
30min - 當距離上次灑水時間未夠
30min的時候一直保持靜止狀態 - 而當到了
30min則會觸發灑水的事件
- 一般我們會給灑水機設定一個時間假設

- 這其實也是節流的最基本的概念了,說白了就是在間隔一段時間執行一次
- 我們上面的灑水可以理解為觸發事件,而我們上面標注的其他資訊也就只有
30min和當前時間,這兩個就是節流的主要要素了, - 當然上面的是我們的生活中的例子,那我們在我們的日常開發中其實也經常用到,比如我們滾動滑鼠滾輪監聽滾動條位置,防止按鈕多次點擊等,
?? 手寫節流
- 說了這么多,相信大家大概理解了
節流的概念,那我們現在來實作一個節流吧,假設我們現在要實作一個滑鼠滾動列印事件,想讓它在3s執行一次,這時候我們該怎么寫呢?

- 首先我們先模擬一個觸發事件,
// throttle.js
function scrollTest(){
console.log('現在我觸發了')
}
document.addEventListener('scroll',scrollTest)
- 接下來我們封裝一個節流函式,跟防抖一樣我們也需要利用閉包,順便再加一個引數接收節流時間,
// throttle.js
...
function throttle(fun,time){
return function(){
fun()
}
}
document.addEventListener('scroll',throttle(scrollTest,3000))
- 因為我們的節流是在一段時間內執行一次也就是說如果兩次滑鼠滾動的時間間隔未到所設定的時間則不執行,
- 那我們可以記錄一下每次滾動的時間戳來進行對比,
// throttle.js
...
function throttle(fun,time){
let t1=0 //初始時間
return function(){
let t2=new Date() //當前時間
if(t2-t1>time){
fun()
t1=t2
}
}
}
- 我們會記錄兩個時間一個是
t1代表初始時間一個是t2代表當前時間,如果當前時間距離上一個時間也就是初始時間大于所設定的time, - 那我們就可以執行
fun()并且把初始時間變更為這一次執行的時間,這樣每次我們執行過后t1就變成了上一次執行的時間, - 這樣我們的一個節流功能就完成了,
// throttle.js
...
function throttle(fun,time){
let t1=0 //初始時間
return function(){
let t2=new Date() //當前時間
if(t2-t1>time){
fun()
t1=t2
}
}
}
- 當然我們也需要像防抖一樣改變
this指向和接收引數,最后完成后是這樣的,
// throttle.js
...
function throttle(fun,time){
let t1=0 //初始時間
return function(){
let t2=new Date() //當前時間
if(t2-t1>time){
fun.apply(this,arguments)
t1=t2
}
}
}
- 至此一個節流函式就手寫完成了,是不是也不會很難呢?
- 總而言之
節流就是在一段時間內不斷操作而在你規定的時間內只執行一次的一種提高性能的方法
👋 寫在最后
- 首先還是很感謝大家看到這里,這次的文章就分享到這里~
- 對于
防抖和節流一個最主觀的判斷方法就是:在10s內你瘋狂點擊一個按鈕,如果使用了防抖則會只執行一次,而你使用了節流則會每隔一段時間執行一次,這個時間可以自己來掌控, - 當然
防抖和節流的變形還是有很多的,根據不同的需求來變換不同的函式但是萬變不離其宗,只要你搞懂了上面的方法,其他的就沒有問題了, - 如果您覺得這篇文章有幫助到您的的話不妨🍉一鍵三連🍉支持一下喲~~😛您的支持就是我更新的最大動力,
- 如果想跟我一起討論和學習更多的前端知識可以加入我的前端交流學習群,大家一起暢談天下~~~
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/306473.html
標籤:其他
