防抖(debounce)的定义:触发高频函数事件后,n秒内函数只能执行一次,如果在n秒内这个事件再次被触发的话,那么会重新计算时间。(最后一个人说了算)
节流(throttle)的定义:高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。(第一个人说了算)
个人理解防抖和节流的不同点和相同的地方:
区分:防抖动和节流本质是不一样的。防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。
共同:这两兄弟的本质都是以闭包的形式存在,每次触发事件时都判断当前是否有等待执行的延时函数
鄙人用纸(方便)简单画一张幼儿园水平的图(并非无意贬低幼儿园小朋友),可能还没啥用:
上面说了那么多,感觉还是跟没说一样,举一些使用场景来加深理解吧。
防抖可用于:
1、search搜索联想,用户在不断输入值时,用防抖来节约请求资源。类似以前常使用lodash来解决搜索防抖的问题。
2、频繁操作点赞和取消点赞,因此需要获取最后一次操作结果并发送给服务器
节流可用于:
1、点击按钮,鼠标不断点击触发,mousedown(单位时间内只触发一次)
2、window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用节流来让其只触发一次
下面是实现代码
实现防抖:
1 function debounce(fn) { 2 let timeout = null; // 创建一个标记用来存放定时器的返回值 3 return function () { 4 clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉 5 timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数 6 fn.apply(this, arguments); // 修正 this 指向问题 7 }, 500); 8 }; 9 } 10 function sayHi() { 11 console.log('防抖成功'); 12 } 13 let box = document.querySelector('body') 14 box.addEventListener('click', debounce(sayHi))
实现节流:
1 function throttle(fn) { 2 let canRun = true; // 通过闭包保存一个标记 3 return function () { 4 if (!canRun) return; // 在函数开头判断标记是否为 true,不为 true 则 return 5 canRun = false; // 立即设置为 false 6 setTimeout(() => { // 将外部传入的函数的执行放在 setTimeout 中 7 fn.apply(this, arguments); // 修正this指向问题 8 // 最后在 setTimeout 执行完毕后再把标记设置为 true(关键) 9 //表示可以执行下一次循环了。当定时器没有执行的时候 10 //标记永远是 false,在开头被 return 掉 11 canRun = true; 12 }, 500); 13 }; 14 } 15 function sayHi(e) { 16 console.log(e.target.innerWidth, e.target.innerHeight); 17 } 18 window.addEventListener('resize', throttle(sayHi));