防抖和节流

防抖和节流的作用都是防止函数多次调用。区别在于,假设一个用户一直触发这个函数,且每次触发函数的间隔小于wait,防抖的情况下只会调用一次,而节流的 情况会每隔一定时间(参数wait)调用函数。

防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。

debonce

  1. / func是用户传入需要防抖的函数
  2. // wait是等待时间
  3. const debounce = (func, wait = 50) => {
  4. // 缓存一个定时器id
  5. let timer = 0
  6. // 这里返回的函数是每次用户实际调用的防抖函数
  7. // 如果已经设定过定时器了就清空上一次的定时器
  8. // 开始一个新的定时器,延迟执行用户传入的方法
  9. return function(...args) {
  10. if (timer) clearTimeout(timer)
  11. timer = setTimeout(() => {
  12. func.apply(this, args)
  13. }, wait)
  14. }
  15. }
  16. // 不难看出如果用户调用该函数的间隔小于wait的情况下,上一次的时间还未到就被清除了,并不会执行函

这个debonce函数不是立即执行的

throttle

  1. // 缺陷版本
  2. const throttle = (func, limit) => {
  3. let inThrottle
  4. return function() {
  5. const args = arguments
  6. const context = this
  7. if (!inThrottle) {
  8. func.apply(context, args)
  9. inThrottle = true
  10. setTimeout(() => inThrottle = false, limit)
  11. }
  12. }
  13. }
  14. const throttle = (func, limit) => {
  15. let lastFunc
  16. let lastRan
  17. return function() {
  18. const context = this
  19. const args = arguments
  20. if (!lastRan) {
  21. func.apply(context, args)
  22. lastRan = Date.now()
  23. } else {
  24. clearTimeout(lastFunc)
  25. lastFunc = setTimeout(function() {
  26. if ((Date.now() - lastRan) >= limit) {
  27. func.apply(context, args)
  28. lastRan = Date.now()
  29. }
  30. }, limit - (Date.now() - lastRan))
  31. }
  32. }
  33. }
  34. // 可理解版本
  35. var throttle = function (fn, delay, atleast) {
  36. var timer = null;
  37. var previous = null;
  38. return function () {
  39. var now = +new Date();
  40. if ( !previous ) previous = now;
  41. if ( atleast && now - previous > atleast ) {
  42. fn();
  43. // 重置上一次开始时间为本次结束时间
  44. previous = now;
  45. clearTimeout(timer);
  46. } else {
  47. // 最后一次执行的方法
  48. clearTimeout(timer);
  49. timer = setTimeout(function() {
  50. fn();
  51. previous = null;
  52. }, delay);
  53. }
  54. }
  55. };

应用

Throttling a button click so we can’t spam click
Throttling an API call
Throttling a mousemove/touchmove event handler
Debouncing a resize event handler
Debouncing a scroll event handler
Debouncing a save function in an autosave feature

讲解

https://keelii.com/2016/06/11/javascript-throttle/