原生JavaScript實現函數的防抖和節流
參考:https://www.jianshu.com/p/c8b86b09daf0
想詳細了解的直接戳上面鏈接了,講得非常清楚。下面只給代碼和我自己寫的注釋,幫助理解背后實現的邏輯。
防抖(Debounce)
所謂防抖,就是指觸發事件后在 n 秒內函數只能執行一次,如果在 n 秒內又觸發了事件,則會重新計算函數執行時間。
/**
* @desc 函數防抖
* @param func 函數
* @param wait 延遲執行毫秒數
* @param immediate true 表立即執行(前沿觸發),false 表非立即執行(后沿觸發)
*/
function debounce(func,wait,immediate) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout); // timeout是定時器ID,只有初始化狀態下第一次觸發的時候才不會執行;后續在周期內觸發db函數會清除定時器,避免在周期內初始化timeout導致事件函數被執行
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(() => {
timeout = null; // 如果周期內db函數未觸發,則重新初始化timeout
}, wait)
if (callNow) func.apply(context, args) // 初始化狀態下,立即執行事件函數
}
else {
timeout = setTimeout(function(){ // 在周期內db函數被觸發會更新定時器,延遲事件函數的執行
func.apply(context, args)
}, wait);
}
}
}
節流(Throttle)
所謂節流,就是指連續觸發事件但是在 n 秒中只執行一次函數。節流會稀釋函數的執行頻率。
/**
* @desc 函數節流
* @param func 函數
* @param wait 延遲執行毫秒數
* @param type 1 表時間戳版(前沿觸發),2 表定時器版(后沿觸發)
*/
function throttle(func, wait ,type) {
if(type===1){
let previous = 0;
}else if(type===2){
let timeout;
}
return function() {
let context = this;
let args = arguments;
if(type===1){
let now = Date.now();
if (now - previous > wait) { // 初始狀態下先執行一次事件函數,並且以當前時間戳為時間起點,往后只有經過的時間大於一個周期后觸發th函數才會更新時間的起點並且執行事件函數
func.apply(context, args);
previous = now;
}
}else if(type===2){
if (!timeout) { // 初始狀態下設置定時器,只有在定時器執行后(執行時間函數+初始化狀態)才能重新設置
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
}