节流

https://github.com/mqyqingfeng/Blog/issues/26

实现原理: 持续触发事件,每隔一段时间,只执行一次。节流根据首次和尾次是否执行,实现方式不同。两种主流的实现方式。一种是使用时间戳,一种是使用定时器。

使用时间戳

  1. function throttle(func, wait) {
  2. var previous = 0;
  3. return function () {
  4. var now =+ new Date();
  5. if (now - previous > wait) {
  6. func.apply(this, arguments);
  7. previous = now
  8. }
  9. }
  10. }

使用定时器

  1. function throttle(func, wait) {
  2. var timeFlag;
  3. return function () {
  4. if (!timeFlag) {
  5. timeFlag = setTimeout(() => {
  6. timeFlag = null;
  7. func.apply(this, arguments)
  8. }, wait)
  9. }
  10. }
  11. }

比较

  1. 使用时间戳的会立即执行,使用定时器的会在一定时间后执行
  2. 第一种在事件停止后就没办法再执行,第二种事件停止后依旧会执行一次事件

同时使用时间戳和定时器

需求:鼠标移入时执行,鼠标停止时执行。
第三版

  1. function throttle(func, wait) {
  2. var timeout, context, args, result;
  3. var previous = 0;
  4. var later = function () {
  5. previous = +new Date();
  6. timeout = null;
  7. func.apply(context, args)
  8. };
  9. var throttled = function () {
  10. var now = +new Date();
  11. // 下次触发的剩余时间
  12. var remainging = wait - (now - previous);
  13. context = this;
  14. args = arguments;
  15. if (remainging < 0 || remainging > wait) {
  16. if (timeout) {
  17. clearTimeout(timeout);
  18. timeout = null;
  19. }
  20. previous = now;
  21. func.apply(context, args)
  22. } else if (!timeout) {
  23. timeout = setTimeout(later, remainging);
  24. }
  25. };
  26. return throttled
  27. }

可以配置的截溜函数

leading:false:表示禁止第一次执行
trailing:false表示禁用停止触发回调

  1. function throttle(func, wait, options) {
  2. var timeout, context, args, result;
  3. var previous;
  4. if (!options) options = {};
  5. var later = function () {
  6. previous = options.leading === false ? 0 : new Date().getTime();
  7. timeout = null;
  8. func.apply(context, args);
  9. if (!timeout) {
  10. context = args = null
  11. }
  12. };
  13. var throttled = function () {
  14. var now = new Date().getTime();
  15. if (!previous && options.leading === false) previous = now;
  16. var remaining = wait - (now - previous);
  17. context = this;
  18. args = arguments;
  19. if (remaining <= 0 || remaining > wait) {
  20. if (timeout) {
  21. clearTimeout(timeout);
  22. timeout = null;
  23. }
  24. previous = now;
  25. func.apply(context, args);
  26. if (!timeout) context = args = null;
  27. } else if (!timeout && options.trailing !== false) {
  28. timeout = setTimeout(later, remaining)
  29. }
  30. };
  31. return throttled
  32. }

取消

  1. throttled.cancel = function() {
  2. clearTimeout(timeout);
  3. previous = 0;
  4. timeout = null;
  5. }

注意undersore实现的问题

leading:false 和 trailing: false 不能同时设置

leading:false 和 trailing: false 不能同时设置