一.防抖之前端人话

防抖, 简而言之就是window 中的 resize、scroll, mousedown、mousemove, keyup、keydown等事件频繁的发生, 如果这些事件处理函数有异步方法,容易造成页面的卡顿, 解决的方法之一就是防抖(debounce), 其二是节流(throtter).
防抖和节流到底啥区别: 防抖是事件持续触发,等待事件停止触发后n才执行函数. 节流是事件持续触发的时候,每n秒执行一次函数

  1. function debounce(func, wait) {
  2. let timeout;
  3. return function() {
  4. clearTimeout(timeout);
  5. timeout = setTimeout(func, wait);
  6. }
  7. }

一.func方法中的this和event对象

上面方法中的this是指向window, 如何将this指向当前的作用的对象, 如何获取event对象

  1. function debounce(func, wait) {
  2. let timeout;
  3. return function() {
  4. const context = this;
  5. const args = arguments;
  6. clearTimeout(timeout);
  7. timeout = setTimeout(function() {
  8. func.apply(context, args)
  9. }, wait);
  10. }
  11. }

二.不希望等到n秒后才执行,希望立即执行, 等到停止触发n秒后才可以重新执行, 如何做 ?

  1. function debounce(func, wait, immediate) {
  2. let timeout;
  3. return function() {
  4. const context = this;
  5. const args = arguments;
  6. if(timeout) {
  7. clearTimeout(timeout);
  8. }
  9. if(immediate) {
  10. // 如果执行过,不再执行
  11. const callNow = !timeout;
  12. timeout = setTimeout(function(){
  13. timeout = null;
  14. }, wait);
  15. if(callNow) {
  16. func.apply(context, args);
  17. }
  18. } else {
  19. timeout = setTimeout(function() {
  20. func.apply(context, args);
  21. }, wait);
  22. }
  23. }
  24. }

三.如何返回func函数的返回值?

只有当immediate为true的时候才将func的结果返回, 因为immediate为false的时候, 我们将执行函数放在定时器中,返回结果永远是undefined

  1. function debounce(func, wait, immediate) {
  2. let timeout;
  3. let result;
  4. return function() {
  5. const context = this;
  6. const args = arguments;
  7. if(timeout) {
  8. clearTimeout(timeout);
  9. }
  10. if(immediate) {
  11. // 如果执行过,不再执行
  12. const callNow = !timeout;
  13. timeout = setTimeout(function(){
  14. timeout = null;
  15. }, wait);
  16. if(callNow) {
  17. result = func.apply(context, args);
  18. }
  19. } else {
  20. timeout = setTimeout(function() {
  21. func.apply(context, args);
  22. }, wait);
  23. }
  24. return result;
  25. }
  26. }

四.如何取消debounce函数, eg:debounce间隔是10秒,立即执行, 我只能等到10秒后才能触发执行, 这时候希望有一个按钮, 点击可以取消防抖, 这样再去触发,就可以立即执行, 如何做 ?

  1. function debounce(func, wait, immediate) {
  2. let timeout;
  3. let result;
  4. const debouned = function() {
  5. const context = this;
  6. const args = arguments;
  7. if(timeout) {
  8. clearTimeout(timeout);
  9. }
  10. if(immediate) {
  11. // 如果执行过,不再执行
  12. const callNow = !timeout;
  13. timeout = setTimeout(function(){
  14. timeout = null;
  15. }, wait);
  16. if(callNow) {
  17. result = func.apply(context, args);
  18. }
  19. } else {
  20. timeout = setTimeout(function() {
  21. func.apply(context, args);
  22. }, wait);
  23. }
  24. return result;
  25. }
  26. debouned.cancel = function() {
  27. clearTimeout(timeout);
  28. timeout = null;
  29. }
  30. return debouned;
  31. }

二.节流

一. 时间戳实现

  1. 鼠标第一次移入的时候会立刻执行
  2. 事件停止触发后没有办法再执行 ```javascript

function throttle(func, wait) { let previous = 0 let context let args

return function() { let now = +new Date() context = this args = arguments

  1. if (now - previous > wait) {
  2. func.apply(context, args)
  3. previous = now
  4. }

} }

  1. <a name="0LmuN"></a>
  2. ### 二. 定时器实现
  3. 1. 不会立即执行, n秒后第一次执行
  4. 1. 停止触发后依然会再执行一次
  5. ```javascript
  6. function throttle2(func, wait) {
  7. let timeout
  8. return function() {
  9. let context = this
  10. let args = arguments
  11. if(!timeout) {
  12. timeout = setTimeout(function(){
  13. timeout = null
  14. func.apply(context, args)
  15. }, wait)
  16. }
  17. }
  18. }