函数节流和函数防抖
函数节流概念: 函数预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期
比如在做网页的时候有个需求,就是浏览器窗口改变的时候需要改一些页面元素大小,于是乎很自然的想到了window的resize事件
<script>
var n = 0;
function resizeHandler () {
console.log(n++);
}
window.onresize = resizeHandler
</script>
效果随着窗口大小改变不停打印n的值
使用函数节流
<script>
var n = 0;
function resizeHandler () {
console.log(n++)
}
function throttle (method, delay) {
var timer = null;
return function () {
var context = this;
var args = arguments;
clearTimeout(timer);
timer = setTimeout(() => {
method.apply(context, args)
}, delay);
}
}
window.onresize = throttle(resizeHandler, 500);//因为返回函数句柄,不用包装函数了
</script>
窗口大小改变,不断打印n的值,但不要一直打印,500ms内如果没有继续拖动,则打印值
对于函数节流,有如下几个场景:
- 游戏中的刷新率
- DOM元素拖拽
- Canvas画笔功能
函数防抖:函数执行过一次后,在等待某时间段内不能再次执行;在等待时间内触发此函数,则重新计算等待时间
<script>
var n = 0;
function debounce (method, wait, flag) {
var timer = null;
var context, args, result, timestamp;
var later = function () {
var oDate = new Date();
var last = oDate.getTime() - timestamp; // 计算第一次时间戳与当前时间戳的差值。
if (last < wait && last >= 0 ) { // 在等待时间内触发此函数,重新计时。
timer = setTimeout(later, wait - last);
} else {
timer = null;
if (!flag) { // 限制flag 为true时,执行回调函数。
result = method.apply(context, args);
if (!timer) {
context = args = null
}
}
}
}
return function () {
var oDate = new Date();
var callNow = flag && !timer; // 代表第一次调用立即执行。
timestamp = oDate.getTime(); // 记录下当前时间戳
context = this;
args = arguments;
if (!timer) { // 第一次触发时,timer为空,进入此分支
timer = setTimeout(later, wait);
}
if (callNow) { // 第一次触发且flag为true,进入此分支
result = method.apply(context, args);
context = args = null
}
return result;
}
}
window.onscroll = debounce (function () {
console.log(1)
}, 500, false)
</script>
此次封装支持两种形式:
flag为true时,连续事件触发时,只会在第一次触发的时候执行回调。
flag为false时,连续事件触发时,只会在最后一次触发的时候执行回调。
对于函数防抖,有以下几种应用场景:
- 给按钮加函数防抖防止表单多次提交。
- 对于输入框连续输入进行AJAX验证时,用函数防抖能有效减少请求次数。
-
判断scroll是否滑到底部,滚动事件+函数防抖
总的来说,适合多次事件一次响应的情况
欢迎大家点赞和评论,如有不足之处请大神指出,刚入门,请多多指教。