# 先说一下我是如何发现问题的吧
## 我就先按照各种教程上这样写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button type="submit" onclick="debounce(()=>{console.log('123123')},1000)"></button>
<script>
function debounce(fn, wait) {
var timeout = null;
return function () {
if (timeout !== null) clearTimeout(timeout);
timeout = setTimeout(fn, wait);
}
}
</script>
</body>
</html>
发现并不能实现 我想要的功能
于是我就开始研究此类问题
我发现
当你点击时,每一次都会执行这个函数,并且每一次返回的函数也是新的,并没有达到闭包要求
于是我改造了代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button type="submit" onclick="throttles()">触发</button>
<script>
function throttle(fn, delay) {
var times = null
let that = this
return function (...arre) {
if (times) {
clearTimeout(times)
}
times = setTimeout(fn, delay);
}
}
let throttles = throttle(() => { console.log("12121") }, 1000)
</script>
</body>
</html>
这样就能完美的实现这个功能了
讲讲这个原理可以嘛?
没问题
当页面加载时 会立即执行 throttles函数 因为这个是立即执行函数 执行完了之后
此刻onclick 就等于返回的函数 所以每一次点击都相当于在执行内层函数 而内层函数又使用了外层函数的变量 ,所以外层函数的作用域又不会消失,就形成了闭包函数,当在1秒内调用这个函数时定时函数还未从宏任务中执行完毕,所以上一个变量值还在就会从宏任务中清除这个任务,并压入新的任务
这样就实现了防抖的作用
说我骗人,那就上图
这下清晰了吧,节流只需要把清除定时器的去掉就行,