一、防抖与节流的联系
相同点:防抖(Debounce)和节流(Throttle)都是用来控制某个函数在一定时间内触发次数,两者都是为了减少触发频率,以便提高性能以及避免资源浪费
不同点:节流是第一个说了算,后续都会被节流阀屏蔽掉,防抖是最后一个说了算,前面启用的都会被清除
二、节流函数
1.定义:节流就是指连续触发事件但是在 n 秒中只执行一次函数,节流会稀释函数的执行频率
2.分类:
(1)使用时间戳实现的节流函数会在第一次触发事件时立即执行,以后每过 delay 秒之后才执行一次,并且最后一次触发事件不会被执行
节流函数输入一个函数并返回一个函数(高阶函数)
节流使用闭包,保存上一次触发回调的时间 last,执行函数 func,时间阀值delay
在要执行 func 时,当前时间与上一次触发时间进行比较,如果时间间隔大于interval(now - last >= interval),执行函数 (context, args)
// 时间戳方式
// 节流 事件连续触发在n秒内只触发一次
function throttle(func, interval) {
// last为上一次触发回调的时间
let last = 0;
// 将throttle处理结果当作函数返回
return function() {
// 保留调用时的this上下文
let context = this;
// 保留调用时传入的参数
let args = arguments;
// 记录本次触发回调的时间
let now = ();
// 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
if (now - last >= interval) {
// 如果时间间隔大于我们设定的时间间隔阈值,则执行回调
last = now
(this, args);
}
}
}
(2)定时器实现的节流函数在第一次触发时不会执行,而是在 interval
秒之后才执行,当最后一次停止触发后,还会再执行一次函数
// 定时器方式
function throttle1(func, interval) {
let sign = true;
return function() {
// 在函数开头判断标志是否为 true,不为 true 则中断函数
if (!sign) return;
// sign 设置为 false,防止执行之前再被执行
sign = false;
setTimeout(() => {
(this, arguments)
// 执行完事件之后,重新将这个标志设置为 true
sign = true;
}, interval)
}
}
3.使用场景
节流一般用于鼠标的跟随动画实现,scroll
,resize
, touchmove
, mousemove
等极易持续性促发事件的相关动画问题,降低频率
<!-- 节流函数 获取鼠标在元素上的坐标 -->
<style>
.container {
width: 100px;
height: 100px;
background-color: #3496db;
}
</style>
<div class="container"></div>
<script>
function throttle(func, interval) {
let last = 0;
return function() {
let args = arguments;
let now = ();
if (now - last > interval) {
(this, args);
last = now
}
}
}
('mousemove', throttle(function(e){
()
}, 2000))
</script>
三、防抖函数
1.定义:防抖就是指触发事件后在 n
秒内函数只能执行一次,如果在 n
秒内又触发了事件,则会重新计算函数执行时间
<input type="text">
<script>
// 防抖 事件触发 n 秒后执行一次, 如果在 n 秒内重复触发则重新计算函数执行时间
function debounce(func, interval) {
// 设置标识符
let timer = null;
return function () {
// 判断定时器是否存在,清除定时器
timer && clearTimeout(timer)
// 重新调用setTimeout
timer = setTimeout(() => {
(this, arguments)
timer = null;
}, interval)
}
}
let input = ('input');
let inputValue = debounce(inputChange, 1000)
function inputChange(e) {
()
}
('keyup', inputValue)
</script>
防抖函数也是一个高阶函数,也使用了闭包,与节流不同,此处闭包保存的是setTimeout
返回的 timer
,用于在后续持续触发之前及时取消定时器
2.使用场景
防抖一般用于表单元素的校验,如手机号,邮箱,用户名等,部分搜索功能的模糊查询结果实现
<!-- 防抖函数 表单校验 -->
<input type="text" replacer="请输入内容">
<script>
let input = ('input');
function debounce(func, interval) {
let timer;
return function() {
timer && clearTimeout(timer)
let args = arguments;
timer = setTimeout(() => {
(this, args)
timer = null;
}, interval)
}
}
('keyup', debounce(function(event) {
let regexp = /\d/g;
if(!()) {
('输入错误')
} else {
()
}
}, 1000))
</script>