防抖与节流及手写代码 | JavaScript

分为文字版和思维导图版(在文末)

一、防抖

1.含义

当事件被触发n秒后再执行回调,如果在n秒内又被触发,则重新计时。

2.使用场景

  • 搜索输入框的联想功能,当不再输入后的几百毫秒再去发送请求,减少服务器压力。
  • 不停改变浏览器窗口大小resize,引起浏览器的重排,消耗性能

3.函数实现

function debounce(func, delay) {
    
              
    let timer; 
    return function () {
    
     
        let context = this;                 
        let args = arguments;
        if (timer) {
    
    
            clearTimeout(timer);
        }
        timer = setTimeout(function () {
    
    
            func.apply(context, args);      
            // 其实就是 context.func(args)
        }, delay);
    };
}

二、节流

1.含义

规定在一个单位时间内只能触发一次函数,若在单位时间内多次触发,则只执行1次。

2.使用场景

  • 监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断
  • 鼠标不断点击触发,mousedown(单位时间内只触发一次)

3.函数实现

(1)时间戳

function throttle(fn, wait) {
    
    
  var args;
  // 前一次执行的时间戳
  var previous = 0;
  return function() {
    
    
    // 将时间转为时间戳
    var now = +new Date();
    args = arguments;
    // 时间间隔大于延迟时间才执行
    if (now - previous > wait) {
    
    
      fn.apply(this, args);
      previous = now;
    }
  };
}

(2)定时器

function throttle(fn, wait) {
    
    
  var timer, context, args;
  return function() {
    
    
    context = this;
    args = arguments;
    // 如果定时器存在,则不执行
    if (!timer) {
    
    
      timer = setTimeout(function() {
    
    
        // 执行后释放定时器变量
        timer = null;
        fn.apply(context, args);
      }, wait);
    }
  };
}

4.拓展

函数实现:不希望非要等到事件停止触发后才执行,我希望立刻执行函数,然后等到停止触发 n 秒后,才可以重新触发执行

function debounce(func, wait, immediate) {
    
    
    var timeout, result;

    return function () {
    
    
        var context = this;
        var args = arguments;
        if (timeout) {
    
    
          clearTimeout(timeout);
        }
        if (immediate) {
    
    
            // 如果已经执行过,不再执行
            var callNow = !timeout;
            timeout = setTimeout(function(){
    
    
                timeout = null;
            }, wait)
            if (callNow) {
    
     
              result = func.apply(context, args)
            }
        }
        else {
    
    
            timeout = setTimeout(function(){
    
    
                func.apply(context, args)
            }, wait);
        }
        return result;
    }
}

三、对比

1.相同

  • 本质目的是为了节省程序的性能(防止高频函数调用)
  • 都借助了闭包的特性来缓存变量(状态)
  • 都可以使用setTimeout实现

2.不同

侧重点不同:防抖侧重于稳定只能执行一次,而节流强调限周期内次数,即执行频率,不限制所有时间内的总次数

四、lodash

lodash中文文档
https://www.lodashjs.com/docs/lodash.debounce
https://www.lodashjs.com/docs/lodash.throttle


思维导图

防抖与节流-思路

防抖与节流


参考文章链接
https://juejin.cn/post/6893748375372431368#heading-1
https://juejin.cn/post/6844903752063778830#heading-2
https://juejin.cn/post/6844903795420299278

猜你喜欢

转载自blog.csdn.net/qq_42376600/article/details/127797322