防抖(Debounce)和節(jié)流(throttle)都是用來控制某個函數(shù)在一定時間內(nèi)執(zhí)行多少次的技巧,兩者相似而又不同。
函數(shù)節(jié)流(throttle):是讓一個函數(shù)無法在很短的時間間隔內(nèi)連續(xù)調(diào)用,當(dāng)上一次函數(shù)執(zhí)行后過了規(guī)定的時間間隔,才能進(jìn)行下一次該函數(shù)的調(diào)用。
函數(shù)去抖(debounce):讓一個函數(shù)在一定間隔內(nèi)沒有被調(diào)用時,才開始執(zhí)行被調(diào)用方法。
兩個方法都是用來提升前端性能,減輕瀏覽器壓力。
防抖:
我們拿最為常見的scroll事件做例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
*{
margin: 0;
padding: 0;
}
div{
height: 3000px;
}
</style>
</head>
<body>
<div>
</div>
<script>
window.onload=function () {
window.onscroll=function () {
console.log(document.body.scrollTop || document.documentElement.scrollTop);
}
}
</script>
</body>
</html>
未作防抖處理之前,我們看看會發(fā)生什么

我們滾動鼠標(biāo)滾輪,短時間內(nèi)觸發(fā)多個事件,DOM操作是很耗費(fèi)性能的,如果在監(jiān)聽中,做了一些DOM操作,那無疑會給瀏覽器造成大量性能損失。
進(jìn)行處理后的代碼如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
*{
margin: 0;
padding: 0;
}
div{
height: 3000px;
}
</style>
</head>
<body>
<div>
</div>
<script>
window.onload=function () {
let timer;
window.onscroll=function () {
if(timer){
clearTimeout(timer);
}
timer=setTimeout(function () {
console.log(document.body.scrollTop || document.documentElement.scrollTop);
},200);
}
}
</script>
</body>
</html>
防抖效果如下

對防抖函數(shù)進(jìn)行封裝
/**
*防抖函數(shù)封裝
*@method debounce
*@param {function|element}method
*@param {number|element}delay
*@return {function|element}
*/
function debounce(method,delay){
let timer;
return function () {
if (timer){
clearTimeout(timer);
}
timer=setTimeout(function () {
let params=Array.prototype.slice.apply(arguments);
method.apply(this,params);
},delay)
}
}
window.onscroll=debounce(function () {
console.log(document.body.scrollTop || document.documentElement.scrollTop);
},200);
我認(rèn)為防抖效果應(yīng)該會應(yīng)用在電商平臺訂單提交之中,不可能讓用戶瘋狂點(diǎn)擊提交訂單。
節(jié)流:我們拿點(diǎn)擊事件做例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>
點(diǎn)擊
</button>
<script>
let btn=document.getElementsByTagName("button")[0];
btn.onclick=function () {
console.log(1);
}
</script>
</body>
</html>
未進(jìn)行節(jié)流處理

進(jìn)行節(jié)流處理后
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>
點(diǎn)擊
</button>
<script>
let btn=document.getElementsByTagName("button")[0];
let flag=true;
btn.onclick=function () {
if (flag){
console.log(1);
flag=false;
setTimeout(function () {
flag=true;
},2000);
}
}
</script>
</body>
</html>
效果如下

對節(jié)流函數(shù)進(jìn)行封裝
/**
* throttle
* @param method
* @param delay
* @return {Function}
*/
let flag=true;
function throttle(method,delay){
return function () {
if (flag){
let params=Array.prototype.slice.apply(arguments);
method.apply(this,params);
flag=false;
setTimeout(function () {
flag=true;
},delay)
}
}
}
節(jié)流函數(shù)的使用還是很常見的,比如無縫輪播圖的換頁點(diǎn)擊,不能讓用戶一直點(diǎn)擊按鍵,至少應(yīng)當(dāng)?shù)却隧摲撏瓿伞?br> ps:最近用支付寶里面的餓了么點(diǎn)外賣,由于等了很久沒來,連續(xù)多次點(diǎn)了催單按鈕,然后“奇怪”的事情就發(fā)生了,我停止點(diǎn)擊后,每隔一秒就出現(xiàn)已催單的提示,就這樣持續(xù)了接近半分鐘,我感覺這個現(xiàn)象應(yīng)該和防抖和節(jié)流有關(guān)。