防抖 : 在规定时间内触发,规定时间会从新计时,直到最后一次触发,规定时间后才会触发。 参考: 游戏技能释放需要蓄力,每次点击技能都会从新蓄力,只有蓄力满了才能释放技能。
防抖:限制函数执行的频次,避免函数触发频率过高而引发 延迟, 卡顿等现象。
用法如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button id="myBtn" onclick="btnAction()" >点击 </button>
</body>
<script>
// 事件
const task = (name) => {
console.log('commit message!!!',name)
}
const debounceTask = debounce(task, 3000)
function debounce(fn, delay) {
let timer
//这里return的是一个函数,需要在事件绑定中再次调用。
return function (...args) {
// 清处时间
if (timer) clearTimeout(timer)
//这里在第一次点击时会等延迟完后才会执行。
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
const debounceTask = debounce(task, 3000)
function btnAction(){
debounceTask(11111)
}
// document.getElementById("myBtn").addEventListener("click", debounceTask);
</script>
</html>
第一种:事件触发,需要等延迟时间结束后才会执行。
function debounce(fn, delay) {
let timer
return function (...args) {
// 清处时间
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
第二种:事件触发,立即执行
function debounce(fn, delay) {
let timer
return function (...args) {
// 清处时间
if (timer) {
clearTimeout(timer)
}
// 这里的timer在第一次执行时,只是在上面声明了,没有赋值所以是undifiend,而undifiend 取反是true,所以第一次点击时会立即执行。 而后面的点击timer会被定时器附上时间id,值类型是数字 再取反是false,所以第二次之后就不回走这个if语句了 。
if (!timer) {
console.log(' right now!!!');
fn.apply(this.args)
}
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
第三种:根据参数来判断
function debounce(fn, wait, immediate) {
// timer用来记录当前函数执行状态
let timer = null
return function () {
// 利用this和arguments获取作用域和变量
let args = arguments
let context = this
// 这里的timer在第一次执行时,只是在上面声明了,没有赋值所以是undifiend,而undifiend取反是true,所以第一次点击时会立即执行。 而后面的点击timer会被定时器附上时间id,值类型是数字 再取反是false,所以第二次之后就不回走这个if语句了 。
if (immediate && !timer) {
fn.apply(context, args)
}
// 清理掉正在执行的函数并重新执行
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(context, args)
}, wait)
}
}