防抖函式與節流函式
本文寫于 2020 年 6 月 1 日
今天看到了兩個函式,防抖函式與節流函式,
這倆函式名字看起來是不是十分高端?
但是對于前端而言,這一年多的學習讓我明白——不要望文生義,更不要望文生畏!
那么,啥是防抖?啥是節流?
請先思考兩個故事,
故事一:
首先想象我們回到了 25 年前,我們的網速還是在 18kb/s ,
這個時候我們訪問了現代的淘寶,準備備戰 618,
但是很不幸,因為網速過慢,我們在購買的時候遲遲沒有反應,所以我們一次又一次的點擊“立即購買”,
假設這個淘寶是平行空間的淘寶,他們沒有做任何防止重復提交的技術,
那么我們的多次點擊,將會把所有的請求全部上傳!恭喜你,購買了 N 件同樣的商品,
故事二:
如果我們有 10 部電梯和 10 個用戶,這些用戶會以 5 秒鐘的間隔依次進入電梯,并且用戶一旦進入電梯,電梯門就會關閉,不可停止,
那這個時候,10 個用戶,就會乘著 10 個電梯,順著相差 5 秒的電梯一起上行,
這也太浪費資源了!
1. 防抖
所謂防抖函式,就是當我們連續的呼叫 foo() 函式時,總是會中斷之前的函式,然后立即執行最新的一次呼叫,
為啥要這么做呢?想想剛剛的電梯故事,多么的浪費資源!
但是如果這個故事發生在日常的生活中,我們會如何處理?
如果僅僅在短時間內,我們完全是可以按住“上行”按鈕停住電梯門的,這樣我們所有的人就能一起上行,
這就是防抖,
防抖函式具體到底有哪些用途呢?
? 給按鈕加函式防抖防止表單多次提交;
? 對于輸入框連續輸入進行 Ajax 驗證時,用函式防抖能有效減少請求次數;
? 判斷頁面滑動何時停止,
2. 節流
節流規定一個單位時間內,只能有一次觸發事件的回呼函式執行,如果在同一個單位時間內某事件被觸發多次,只有一次能生效,
當我們在撰寫網頁的時候,如果我們需要實作 DOM 拖拽功能,一般都會給 move 事件添加回呼函式,
但是真正運行的時候我們會發現:每當元素稍微移動一點,就會觸發了大量的回呼函式,導致瀏覽器直接卡死,
除了 DOM 另外一個例子就是電影,
我們知道當 1 秒內連續播放 24 張以上的圖片時,人的眼中這些圖片就會形成一個連貫的影片,
所以在電影的播放中基本是以每秒 24 張的速度播放的,為什么不 500 張或更多是因為 24 張就可以滿足人類視覺需求的時候,500 張就會顯得很浪費資源,
對于函式節流,有如下幾個場景:
? 游戲中的重繪率;
? DOM 元素拖拽;
? Canvas 畫筆功能,
上代碼:
/*
* 防抖函式 debounce
* fn 是執行的函式,wait 是防抖的時間間隔
*/
function debounce(fn, wait) {
// 用一個變數來記錄是否到達了防抖的時間
let timer = null
return function() {
// 如果 timer 不為空,就會清除定時器,并且將 timer 清空
if (timer) {
clearTimeout(timer)
timer = null
}
timer = setTimeout(() => fn(), wait)
}
}
/*
* 節流函式 throttle
* fn 是執行的函式,gapTime 是節流的時間間隔
*/
function throttle(fn, gapTime) {
let lastTime = null;
return function () {
let nowTime = + new Date()
// 如果 lastTime 是 null,或者兩次呼叫的時差超過了節流時間,才會執行函式
if (!lastTime || nowTime - lastTime > gapTime) {
fn();
// 執行完畢后將時間同步
lastTime = nowTime
}
}
}
這里我們可以看到,其實是 return 的用來操作 timer 和 lastTime 的函式就是一個閉包,
如果不理解,可以不要外層的函式,直接將 timer 和 lastTime 放在全域作用域,再去嘗試理解,
總結
一言以蔽之:函式防抖和函式節流,是在時間軸上控制函式的執行次數所用的函式,
(完)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/77930.html
標籤:JavaScript
上一篇:js移除陣列中指定元素【轉】
