- 前言
- 防抖概念
- 防抖应用场景
- 第一版:全局变量timer
- 第二版:闭包版
- 第三版:this版
- 第四版:event版
1、前言
节流和防抖用来处理一些频繁的事件触发,减少请求频率
onclick
,keyup
,keydown
等。如用户不断点击提交表单等操作- window的
resize
、scroll
等
2、防抖概念
通过设置定时器实现。如果用户点击按钮,设置定时器,在N秒内,当用户再次点击,清除定时器,再重新设置(在N秒内,无论用户点击多少次,只执行它的最后一次)。
简单理解:在事件触发N秒后执行,在N秒内又被触发,则重新计时
3、防抖应用场景
- 按钮提交场景:防止多次提交按钮,只执行最后提交的一次
- 搜索框联想场景:防止联想发送请求,只发送最后一次输入
- 浏览器滚动scroll,会不断调用绑定的事件,为减少请求不浪费资源,在滚动结束时,加载数据
4、第一版:使用全局变量timer
<button id="submit">按钮</button>
let timer = null
function debounce() {
if (timer !== null) {
clearTimeout(timer) // 在2秒内,再一次点击清除原来的timer
}
timer = setTimeout(() => {
console.log('事件处理')
}, 2000)
}
const submit = document.getElementById("submit")
submit.onclick = debounce // 在js中绑定函数后面不写()
5、第二版: 利用闭包实现一个防抖的方法
优化点:
- 将第一版的全局变量timer放到函数内部,使用闭包更改timer
- 业务逻辑和防抖方法写在一起了,后续业务逻辑变多不利于维护
function callBack() {
console.log(this)
}
function debounce(func, wait) {
var timer
return function () {
clearTimeout(timer)
timer = setTimeout(() => {
func()
}, wait)
}
}
const submit = document.getElementById("submit")
// 使用闭包,返回一个函数。要执行函数所以debounce()调用
submit.onclick = debounce(callBack, 1000)
6、 第三版: 改变this指向,将this指向正确的对象
如果此时在callBack函数中输出this, this指向window。
function debounce(func, wait) {
var timer
return function () {
var context = this
clearTimeout(timer)
timer = setTimeout(() => {
func.call(context)
}, wait)
}
}
const submit = document.getElementById("submit")
submit.onclick = debounce(callBack, 1000)
7、第四版:event版
- JavaScript 在事件处理函数中会提供事件对象 event,我们修改下 callBack 函数
- callBack 函数可能是有返回值的,所以我们也要返回函数的执行结果
function callBack(e) {
console.log(e) // 打印出对象
console.log(this)
}
function debounce(func, wait) {
var timer
var result;
return function () {
let context = this;
let args = arguments;
clearTimeout(timer)
timer = setTimeout(function () {
// func函数可能是有返回值的,所以也要返回函数的执行结果
result = func.call(context, args)
timer = null
}, wait)
return result
}
}
const submit = document.getElementById("submit")
submit.onclick = debounce(callBack, 1000)
如有错误或者不严谨的地方,欢迎指正。
本文参考冴羽的文章: https://juejin.cn/post/6844903480239325191