防抖
函数防抖:短时间多次触发同一事件,只执行 最开始 或 最后 一次操作。
function debounce(func, ms = 1000) { let timer; return function(...args) { console.log(args); if (timer) { clearTimeout(timer); } timer = setTimeout(() => { func.apply(this, args); }, ms); }; } const task = () => {console.log('run task')}; const debounceTask = debounce(task, 1000); window.addEventListener('click', debounceTask); // click 可以换成 scroll
防抖原理:
就 click 来说,如果 1s 内,点击很多次的话,debounceTask(指匿名函数) 就会执行很多次。那 task 函数也会多次调用,造成不必要的浪费。如图说明吧:
对 debounce 函数返回的匿名函数中 args 参数(这里可忽略)的存在作出说明:
const debounceTask = debounce(task, 1000) 其实返回的是匿名函数。
点击页面触发 window.addEventListener('click', debounceTask) 事件,debounceTask 会执行。
这里 debounceTask 没有传递参数,打印 args 会看到有个事件对象,这里的原因是因为:
在浏览器中,如果函数执行没有传递参数,会默认有个浏览器事件对象作为参数,如监听的是点击 click 事件的话 args 就是 [PointerEvent]
将 click 换成 scroll,如果在函数不防抖,要执行很多次了~
完整案例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, maximum-scale=1, minimum-scale=1,initial-scale=1"/> <title>Title</title> <style> body { overflow: scroll; height: 10000px; border: 2px solid; } input { margin-left: 20px; width: 20px; height: 20px; } </style> </head> <body> <p>函数防抖:短时间多次触发同一事件,只执行最后或最开始的一次。</p> <p>这里以点击事件做测试</p> <input type="checkbox"/> <input type="checkbox"/> <input type="checkbox"/> <input type="checkbox"/> <input type="checkbox"/> <script> function debounce(func, ms = 1000) { let timer; console.log("匿名函数前的 timer", timer); return function(...args) { console.log("匿名函数后的 timer", timer); if (timer) { clearTimeout(timer); } timer = setTimeout(() => { func.apply(this, args); }, ms); }; } const task = () => {console.log('run task')}; const debounceTask = debounce(task, 1000); window.addEventListener('click', debounceTask); </script> </body> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script> /* 节流:函数在一段时间内多次调用,仅第一次有效。 防抖:函数在一段时间内多次调用,仅最后一次有效。 * */ // window.addEventListener('scroll', throttle2(scrollFun, 1000)); window.addEventListener('scroll', debounce(scrollFun, 500)); function scrollFun(e) { console.log('窗口大小改变了'); } /* 节流—时间戳方式 */ function throttle(func, delay) { var last = 0; return function () { var now = Date.now(); /* 一开始滚动的时候就执行,后面是隔一定秒数再执行,再滚动时,先获取的 now 值,间隔时间 超过 delay 时间的话 ,now > delay + last,执行函数。 * */ if (now >= delay + last) { func.apply(this, arguments); last = now; } else { console.log('********** wait '); } } } /* 节流—定时器方式 */ function throttle2(func, delay) { var timer = null; return function () { if(!timer) { func.apply(this, arguments); timer = setTimeout(function() { timer = null; }, delay); } else { console.log('********** wait '); } } } /* 防抖 */ function debounce(func, delay) { var timeout; return function () { clearTimeout(timeout); timeout = setTimeout(() => { console.log('run') func.apply(this, arguments); }, delay); } } </script>
不开始最难,迟迟不开始变得又难又慌~