背景问题
在前端开发中有一部分的用户行为会频繁的触发事件,从而频繁地执行函数,而对于DOM操作、资源加载等耗费性能的处理,很可能导致界面卡顿,甚至浏览器崩溃(本质是因为js是单线程的)。
函数节流(throttle)和函数防抖(debounce)可以解决问题。
防抖
函数防抖就是在函数需要频繁触发情况时,只有等足够空闲的事件,才执行,为了避免又有事件触发。
- 常见应用场景:搜索框实时搜索请求数据、拖拽
- 代码实现:
关键点:设置定时器、this的指向、arguments的指向
模拟搜索框实时请求数据👇
1 | var oInp = document.getElementById('inp'); |
上面的代码只能应对发送ajax这种业务,下面进行一下防抖的封装
1 | var oInp = document.getElementById('inp'); |
节流
函数节流就是预定一个函数只有在大于或等于执行周期时才执行,周期内调用不执行。
- 常见应用场景
- 窗口调整
- 页面滚动数据加载
- 防止恶意脚本抢购疯狂点击
代码实现
模拟抢红包的功能👇
这种代码如果被人注入恶意脚本,使得按钮点击事件疯狂触发,服务器和客户端都受不了。为了避免这种情况,使用节流操作。
1
2我抢到<span id="show">0</span>个红包!
<button id="btn">点击</button>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var oSpan = document.getElementById('show');
var oBtn = document.getElementById('btn');
// oBtn.onclick = function () {
// oSpan.innerText = parseInt(oSpan.innerText) + 1;
// }
oBtn.onclick = throttle(function () {
oSpan.innerText = parseInt(oSpan.innerText) + 1;
}, 1000)
function throttle(handler, wait) {
var lastTime = 0;
return function () {
var nowTime = new Date().getTime();
if (nowTime - lastTime > wait) {
handler();
lastTime = nowTime;
}
}
}再改进一下👇
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20var oSpan = document.getElementById('show');
var oBtn = document.getElementById('btn');
oBtn.onclick = throttle(crazyClick, 1000)
function throttle(handler, wait) {
var lastTime = 0;
return function (e) {
var nowTime = new Date().getTime();
if (nowTime - lastTime > wait) {
handler.apply(this, arguments);
lastTime = nowTime;
}
}
}
function crazyClick(e) {
console.log(this, e);
oSpan.innerText = parseInt(oSpan.innerText) + 1;
}
假设无限次触发:防抖函数永远不会真正执行;节流函数则会按照间隔时间执行。
防抖动和节流本质是不一样的。防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。