防抖和节流是js中常用的两种性能优化方式,他们能减少函数的执行次数以及提高代码的性能
防抖
-
防抖是指连续多次触发同一事件,只执行最后一次或者最开始时执行一次。防抖的应用场景比较广泛,例如用户搜索关键词时,可以使用防抖来避免频繁的发起请求
-
也可以这样理解防抖:回城被打断或者回城嘲讽,玩过王者农药的朋友都知道,回城技能大概要站着不动3秒左右才能释放,中途不能移动或者按别的按键。
- 防抖也是,特别像你把对面英雄打死了,一直点回城一直点回城嘲讽他似的
- 一直点回城一直点回城(除了原地抽搐啥也干不了,当然这里是不会抽搐的),除非你点了回城后不再动了,你才能回城成功。
- 防抖就是,你一直执行某个事件,一直执行某个事件,你是执行不了的,只有你最后一次执行它了,不再执行了,那么它才会触发
下面是简单的防抖实现代码
注: 函数名和变量名都用中文代替,方便理解
function 回城() {
console.log('我要回城,你打我呀')
}
设置一个定时器,因为回城有时间的嘛
let timer = null
function 释放回城() {
// 如果存在回城时间,那它肯定刚刚点了回城,得刷新回城时间
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
// 执行回城
回城()
// 定时器清空,毕竟都回城了,要它干嘛
timer = null
}, 3 * 1000)
}
很好,这样就写好了一个防抖代码了
那么我们不能只有回城防抖呀,别的技能也要防抖呢,我们封装一下
function 防抖函数(技能, 执行时间) {
let timer = null
return function() {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
// 执行技能
技能()
timer = null
}, 执行时间)
}
}
把中文变量名改成英文名,再加个技能参数吧
function debounce(fn, delay) {
let timer = null
return function(...arg) {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn(...arg)
timer = null
}, delay)
}
}
以下是用户搜索关键词时时使用防抖的例子
<input type="text" id="searchInp">
<script>
const searchInp = document.getElementById('searchInp')
function search(keyword) {
console.log(`搜索关键词是: ${keyword}`)
.....
}
// 先执行防抖函数, 插入一个定时器,返回一个新的函数
const debounceSearch = debounce(search, 600)
searchInp.addEventListener('input', e => {
// 每次输入都会执行新的函数,看看有没有定时器
debounceSearch(e.target.value)
})
</script>
节流
-
理论: 节流是指多次连续触发同一事件,每隔一定时间触发一次。例如在用户滚动页面时,可以使用节流来避免频繁地触发函数。
-
可以这样理解节流: 王者中的闪现冷却是120秒,当闪现用完后的这120秒中是用不了的,120秒冷却过后才能继续用。所以节流是不是可以理解为技能冷却时间
以下是实现节流的代码
注: 函数名和变量名都用中文代替,方便理解
// 定义一个闪现的技能
function 闪现() => {
console.log('我闪我闪我闪闪闪!!!')
}
// 定义一个技能是否冷却的变量
let 冷却中 = false
// 定义一个释放技能的函数,如果当前处于冷却,那么技能释放不了,return。如果不在冷却,
// 那么释放闪现,冷却变成true,然后定个定时器,120秒后冷却中改成false,又可以用闪现了
function 释放技能() {
if (冷却中) return
闪现()
冷却中 = true
// 定义一个计时器
setTimeout(() => {
冷却中 = false
}, 120 * 1000)
}
这个其实就是节流的代码
那么我们要实现某个技能的节流,并不单单只是闪现的,怎么做呢?
那就定义一个函数,把技能和冷却时间放进去不就好了
function 技能控制函数(技能, 冷却时间) {
let 冷却中 = false
return function() {
if (冷却中) return
技能()
冷却中 = true
setTimeout(() => {
冷却中 = false
}, 冷却时间)
}
}
这不就很完美了嘛,当然,在我们的代码中最好不要用中文变量名,并且技能万一有参数呢,也要传一传
function throttle(fn, time) {
let cd = false
return function(...arg) {
if (cd) return
fn(...arg)
cd = true
setTimeout(() => {
cd = false
}, time)
}
}
以上就是一个完美的节流的方法拉
调用方式如下:
const huicheng(name) {
console.log(`我是 ${name}, 没血了快回城别浪`)
}
const shifang = throttle(huicheng, 90 * 1000)
shifang('典韦')
防抖和节流的使用场景
防抖和节流的应用场景比较广泛,可以在很多具体功能中使用它们来提高代码的性能。例如:
- 在用户输入搜索关键词时,可以使用防抖来避免频繁地向服务器发送请求。
- 在监听窗口大小改变时,可以使用防抖来避免频繁地调整布局。
- 用户频繁的点击按钮时,比如抢购,可以使用节流来避免频繁地触发函数