理论
函数节流:一个函数执行一次后,只有大于设定的周期后才会执行第二次;需要频繁触发函数,处于优化性能角度,在规定时间内只让函数触发一次,后面不生效
函数防抖:一个需要频繁触发的函数,在规定时间内,只让最后一次生效,前面的无效
区别在于:函数节流是周期性进行触发,也就是规定时间内触发的次数也是固定的;函数防抖则不固定,会被打断,打断就需要重新积蓄时长。
打王者的时候,
技能用完需要一段时间冷却,这就是节流;
但是你回城被打断了就得重新回城,这就跟防抖一个道理。
实践
节流函数 throttle (不带参数,带参数)
防抖函数 debounce (不带参数,带参数)
节流函数 throttle
节流函数 throttle有两种实现形式,分别是时间戳和定时器
简单实现一下节流函数 throttle (先不考虑传参)
function throttle(fn, delay) {
let start = 0
return () => {
let end = Date.now()
if (end - start > delay) {
//修正this指向
fn.call(this)
//注意同步时间
start = end
}
}
}
节流函数使用,滚动屏幕测试,设置一下样式使得出现滚动条
html,
body {
height: 500%;
}
document.onscroll = throttle(_ => {
console.log(`触发${Date.now()}`)
}, 200)
由截图可以看出时间间距在200以上,节流成功
现在来看看节流的传参
function throttle(fn, delay) {
let start = 0
return (...args) => {
let end = Date.now()
if (end - start > delay) {
//修正this指向
fn.apply(this, args)
//注意同步时间
start = end
}
}
}
let inputs = document.getElementById('inputs')
let fn = throttle(e => {
console.log(`触发${Date.now()},输入的值为${e.target.value}`)
}, 200)
//监听input输入事件
inputs.addEventListener('input', fn)
html部分写个输入框
<input id="inputs" type="text">
可以看出在我狂敲1的操作下,被节流了几次
与不传参的区别在于:
注意看到传参是时候修改this指向的从call变成apply,便于传入多个参数,接收参数的地方用三个点...
进行展开
上面使用的是时间戳的形式实现节流,还有一个方式是利用定时器实现节流函数
function throttle(fn, delay) {
let timer = null;
let flag = true; //中间媒介
return (...args) => {
if (!flag) return;
clearTimeout(timer);
flag = false; //标志flag为false,使得不会影响后面的执行
timer = setTimeout(() => {
fn.apply(this, args);
flag = true;
}, delay)
}
}
利用标志flag为中间媒介,当flag为true时候,可以进入函数;当flag为false,不可以进入函数,因此不会影响后面的执行
现在我们继续来看防抖函数,也就是需要蓄能的才能回城的函数
防抖函数 debounce
需要一个定时器进行辅助,在规定的时间内,如果没有被打断,则可以执行函数 先来一个不传参数的防抖函数
function debounce(fn, delay) {
let timer = null
//清除定时器
return function () {
clearTimeout(timer)
//重新设置定时器
timer = setTimeout(()=> {
fn.apply(this)
}, delay)
}
}
利用按钮点击进行测试
document.getElementById('btn').onclick = debounce(_ => {
console.log(`触发${Date.now()}`)
}, 200)
html
<button id="btn">按钮</button>
由截图可以看出,多次点击,只有时间超过200的间隔才有生效,在疯狂点击(点击时差200内)情况下,会持续没有输出效果,也就是被打断多次,无法执行函数
现在可以进行传递参数,原理和节流的传参方式一致
function debounce(fn, delay) {
let timer = null
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay)
}
}
let inputs = document.getElementById("inputs")
let fn = debounce((e) => {
console.log(e.target.value)
}, 200)
//监听input事件
inputs.addEventListener("input", fn)
由上图可知,疯狂敲1会一直积蓄,函数不执行,稍微停顿才能执行输出,实现防抖的效果
总结
节流函数:一个函数执行一次后,只有大于设定的周期后才会执行第二次;类似游戏中的技能用完需要一段时间冷却。实际可以应用于获取短信验证码的按钮。
防抖函数:一个需要频繁触发的函数,在规定时间内,只让最后一次生效,前面的无效;类似游戏中你回城被打断了就得重新回城。实际可以应用于搜索框。
欢迎关注我的个人公众号,写文不易,有用的话请点个赞,Thanks♪(・ω・)ノ
本文使用 mdnice 排版