Open jannahuang opened 2 years ago
当事件被触发,达到指定间隔后再执行任务。如果在指定间隔内又被触发,则重新计时,不会执行任务。
生活中的例子: 电脑设置 10 分钟后自动休眠,这期间操作电脑的话,会打断休眠程序。而当停止操作电脑,倒计时开始,当时间达到设定的 10 分钟之后,电脑休眠。
//原理:定时器是否被中断 function debounce(fn, delay) { let timer //初始化定时器 return function () { if (timer) { //如果有定时器,则清除定时器, clearTimeout(timer) } timer = setTimeout(() => { //重新设定定时器 fn.call(this, arguments) //当时间达到,则执行函数 }, delay) } }
单次或多次触发事件之后,在指定间隔时间之内,只执行一次任务。
生活中的例子: 机场大巴每隔半小时发车一辆,不管上车了多少乘客,都是按时间点发车。
//原理:定时器是否存在 function throttle(fn, delay) { let timer //初始化定时器 return function () { if (timer) { //如果有定时器,则不操作 return } timer = setTimeout(() => { //设定定时器 fn.call(this, arguments) //当时间达到,则执行函数 timer = null // 然后清除定时器,当下次触发事件时,重新计时 }, delay) } }
//原理:两次触发的时间差是否大于间隔时间 function throttle(fn, delay) { let previous = 0 //初始化时间,默认 0 return function() { let now = new Date() //获取当前时间 //注意第一次点击时会触发一次,因为 previous 初始值是 0 if(now - previous > delay) { //时间戳运算 fn.apply(this, arguments) // 当结果超过间隔时间,执行函数 previous = now // 并且刷新上次时间为当前时间,以便下次运算 } } }
相同点:
不同点:
函数防抖的应用场景 连续的事件,只需触发一次回调的场景有:
函数节流的应用场景 间隔一段时间执行一次回调的场景有:
可以用以下代码测试:
<html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>防抖 vs 节流</title> </head> <body> <button id="debounce">点我防抖</button> <button id="throttle">点我节流(定时器版)</button> <button id="throttle2">点我节流(时间戳版)</button> <script> window.onload = function() { // 1、获取这个按钮,并绑定事件 var myDebounce = document.getElementById("debounce"); myDebounce.addEventListener("click", debounce(sayDebounce, 1000)); // 1、获取按钮,绑定点击事件 var myThrottle = document.getElementById("throttle"); myThrottle.addEventListener("click", throttle(sayThrottle, 1000)); // 1、获取按钮,绑定点击事件 var myThrottle2 = document.getElementById("throttle2"); myThrottle2.addEventListener("click", throttle2(sayThrottle2, 1000)); } // 2、防抖功能函数,接受传参 function debounce(fn, delay) { // 4、创建一个标记用来存放定时器的返回值 let timeout = null; return function() { // 5、每次当用户点击/输入的时候,把前一个定时器清除 if(timeout) { clearTimeout(timeout); } // 6、然后创建一个新的 setTimeout, // 这样就能保证点击按钮后的 delay 间隔内 // 如果用户还点击了的话,就不会执行 fn 函数 timeout = setTimeout(() => { fn.call(this, arguments); }, delay); }; } // 3、需要进行防抖的事件处理 function sayDebounce() { // ... 有些需要防抖的工作,在这里执行 console.log("防抖成功"); } // 2、节流函数体(定时器版) function throttle(fn, delay) { // 4、创建一个标记用来存放定时器的返回值 let timeout = null; return function() { // 5、在函数开头判断是否存在定时器,存在则中断函数 if(timeout) { return; } // 6、创建定时器 timeout = setTimeout(() => { fn.call(this, arguments); // 7、执行完事件(比如调用完接口)之后,清除定时器 timeout = null; }, delay); }; } // 3、需要节流的事件 function sayThrottle() { console.log("节流成功(定时器版)"); } // 2、节流函数体(时间戳版) function throttle2(fn, delay) { let previous = 0; return function() { let now = new Date() //获取当前时间 if(now - previous > delay) { //时间戳运算 fn.apply(this, arguments) // 当结果超过间隔时间,执行函数 previous = now // 并且刷新上次时间为当前时间,以便下次运算 } }; } // 3、需要节流的事件 function sayThrottle2() { console.log("节流成功(时间戳版)"); } </script> </body> </html>
以上笔记参考彻底弄懂函数防抖和函数节流,JS 防抖与节流,学会手写防抖节流 及其它参考资料
防抖 debounce
当事件被触发,达到指定间隔后再执行任务。如果在指定间隔内又被触发,则重新计时,不会执行任务。
生活中的例子: 电脑设置 10 分钟后自动休眠,这期间操作电脑的话,会打断休眠程序。而当停止操作电脑,倒计时开始,当时间达到设定的 10 分钟之后,电脑休眠。
节流 throttle
单次或多次触发事件之后,在指定间隔时间之内,只执行一次任务。
生活中的例子: 机场大巴每隔半小时发车一辆,不管上车了多少乘客,都是按时间点发车。
定时器实现节流
时间戳实现节流
异同比较
相同点:
不同点:
常见应用场景
函数防抖的应用场景 连续的事件,只需触发一次回调的场景有:
函数节流的应用场景 间隔一段时间执行一次回调的场景有:
可以用以下代码测试:
以上笔记参考彻底弄懂函数防抖和函数节流,JS 防抖与节流,学会手写防抖节流 及其它参考资料