防抖、节流

防抖是控制次数,节流是控制频率

防抖(debounce

所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

  1. function debounce(fn, wait) {
  2. let timeout;
  3. return function () {
  4. let context = this;
  5. let args = arguments;
  6. if (timeout) clearTimeout(timeout);
  7. timeout = setTimeout(() => {
  8. fn.apply(context, args);
  9. }, wait);
  10. }
  11. }
  1. function debounce(fn, wait) {
  2. let timeout;
  3. return function () {
  4. let context = this;
  5. let args = arguments;
  6. if (timeout) clearTimeout(timeout);
  7. let callNow = !timeout;
  8. timeout = setTimeout(() => {
  9. timeout = null;
  10. }, wait);
  11. if (callNow) fn.apply(context, args);
  12. }
  13. }
  1. function debounce(fn, wait, immediate = true) {
  2. let timeout;
  3. return function () {
  4. let context = this;
  5. let args = arguments;
  6. if (timeout) clearTimeout(timeout);
  7. if (immediate) {
  8. let callNow = !timeout; // 根据 timer 是否为 null 来判断是否要执行 fn.
  9. timeout = setTimeout(() => {
  10. timeout = null;
  11. }, wait);
  12. if (callNow) fn.apply(context, args);
  13. } else {
  14. timeout = setTimeout(() => {
  15. fn.apply(context, args);
  16. }, await)
  17. }
  18. }
  19. }

节流(throttle

所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。

  1. function throttle (fn, wait) {
  2. let previous = 0;
  3. return function () {
  4. let now = Date.now();
  5. let context = this;
  6. let args = arguments;
  7. /* 返回函数一直在被调用,但是只有 now - previoust > wait 时,才会调用 fn */
  8. if (now - previous > wait) {
  9. fn.apply(context, args);
  10. previous = now;
  11. }
  12. }
  13. }
  1. function throttle (fn, wait) {
  2. let timeout;
  3. return function () {
  4. let context = this;
  5. let args = arguments;
  6. if (!timeout) {
  7. timeout = setTimeout(() => {
  8. timeout = null;
  9. fn.apply(context, args);
  10. }, wait);
  11. }
  12. }
  13. }
  1. function throttle(fn, wait, immediate = true) {
  2. if (immediate) {
  3. // 注意: var
  4. var previous = 0;
  5. } else {
  6. // 注意: var
  7. var timeout;
  8. }
  9. return function () {
  10. let context = this;
  11. let args = arguments;
  12. if (immediate) {
  13. let now = Date.now(); // 获取当前时间戳
  14. if (now - previous > wait) {
  15. fn.apply(context, args);
  16. previous = now;
  17. }
  18. } else if (!immediate) {
  19. if (!timeout) {
  20. timeout = setTimeout(() => {
  21. timeout = null;
  22. fn.apply(context, args);
  23. }, wait);
  24. }
  25. }
  26. }
  27. }
  1. function throttle(fn, wait = 500) {
  2. let previous = 0
  3. let timer = null
  4. return function anonymous(...args) { // 匿名函数
  5. const now = Date.now()
  6. const remaining = wait - (now - previous)
  7. if(remaining <= 0) {
  8. clearTimeout(timer)
  9. timer = null
  10. previous = now
  11. fn.call(this, ...args)
  12. } else if(!timer) {
  13. // 若间隔时间小于 500ms,此时只过去了 5ms ,那就需要再过 450ms 后再执行。
  14. // 也就说,当前时间还没有超过设定的节流时间,那就需要知道需要等多久才可执行,此时设置一个定时器来定时执行。
  15. timer = setTimeout(() => { // 注意是箭头函数
  16. clearTimeout(timer)
  17. timer = null
  18. previous = Date.now()
  19. fn.call(this, ...args)
  20. }, remaining)
  21. }
  22. }
  23. }