概念

image.png
节流 throttle:n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效。
减少一段时间的触发频率。

  • 场景:scroll

防抖 debounce:n 秒再在执行该事件,若在 n 秒内被重复触发,则重新计时。
在一定的时间间隔内,将多次触发变成一次触发。

  • 场景:resize

可视化演示:http://demo.nimius.net/debounce_throttle/

注意event参数

  1. document.getElementById("app").addEventListener("click",test);
  2. function test(e){
  3. console.log(this);//<div id=app></div> dom对象
  4. console.log(e) //Event对象
  5. }
  6. // addEventListener(event, function, useCapture) 中的 function 回调函数,默认一个参数为event
  7. // https://wonderlust91.github.io/2018/12/06/javascript%E4%BA%8B%E4%BB%B6%E5%9B%9E%E8%B0%83%E5%8F%82%E6%95%B0/

节流throttle

https://code.h5jun.com/letab/edit?html,js,console,output

  1. //🔥时间戳,缺点:第一次会执行,最后少一次
  2. function throttle1(fn, timeout) {
  3. let last = 0;
  4. return function () {
  5. let now = Date.now();
  6. if (now - last >= timeout) {
  7. last = now;
  8. fn.apply(this, arguments); // this是dom,args 第一个是event事件
  9. }
  10. };
  11. }
  12. //🔥定时器,缺点:最后一次也会等一个时间间隔
  13. function throttle2(fn, timeout) {
  14. let timer = null;
  15. return function () {
  16. if (!timer) {
  17. timer = setTimeout(() => {
  18. fn.apply(this, arguments);
  19. timer = null;
  20. }, timeout);
  21. }
  22. };
  23. }
  24. // 结合
  25. function throttle3(fn, timeout) {
  26. let timer = null;
  27. let last = 0;
  28. return function () {
  29. let now = Date.now();
  30. let remaining = timeout - (now - last);
  31. if (remaining <= 0) {
  32. fn.apply(this, arguments);
  33. last = now;
  34. } else if(!timer) {
  35. timer = setTimeout(() => {
  36. fn.apply(this, arguments);
  37. last = Date.now();
  38. timer = null
  39. }, remaining);
  40. }
  41. };
  42. }

防抖debounce

  1. //🔥初级版本 第一次执行延时
  2. function debounce1(fn,wait){
  3. let timer = null;
  4. return function(){
  5. if(timer){
  6. clearTimeout(timer);
  7. }
  8. timer=setTimeout(()=>{
  9. fn.apply(this, arguments);
  10. },wait);
  11. }
  12. }
  13. // 🔥反过来 第一次执行
  14. function debounce2(fn, timeout) {
  15. let timer = null;
  16. return function () {
  17. if (timer) {
  18. clearTimeout(timer);
  19. }
  20. if (!timer) {
  21. fn.apply(this, arguments);
  22. }
  23. timer = setTimeout(() => {
  24. timer = null;
  25. }, timeout);
  26. };
  27. }

参考: 【爪哇教育 2021大厂前端核心面试题详解-路白-哔哩哔哩】https://b23.tv/2CRSnh https://www.bilibili.com/video/BV1Vy4y1y7tj?p=2 https://segmentfault.com/a/1190000017227559 https://github.com/mqyqingfeng/Blog/issues/26 https://www.zoo.team/article/anti-shake-throttle