求教节流问题

var throttle = function(func, delay) {
  var prev = Date.now();
  return function() {
    var context = this;
    var args = arguments;
    var now = Date.now();
    if (now - prev >= delay) {
      func.apply(context, args);
      prev = Date.now();
    }
  }
}
function handle() {
  console.log(Math.random());
}
window.addEventListener('scroll', throttle(handle, 1000));

两个date.now()是怎么运行的 原理是什么

阅读 1.8k
3 个回答

先用闭包的方式在注册的时候初始化了一个时间戳作为节流计时的开始,每次节流函数执行的时候判断当前时间和节流开始的时间差如果大于等于预计时间(delay)就把节流开始计时的时间更新一下,以当前时间节点为下一个节流的开始时间。这样就保证了每一段时间执行一次

这么写节流挺复杂的 其实不用这么多代码吧
执行流程大概是这样: 当滚动滚轮的时候第一次触发throttle, 先保存一个时间prev ;并且把return的函数赋给throttle;
当下次再执行throttle的时候, 此时执行的就是return的那个函数了. 理解了这一点就能懂了. 剩下几句代码就是简单的判断;

其实节流的流程是: 当你滚动一下滚轮, 这个时候事件不是马上执行, 而是设置了一个延时器, 比如延时300ms, 如果在这300ms内你又触发了这个时间, 那就再设置一个延时器, 也不是马上执行, 以此类推; 直到你不触发这个事件了, 且超过300ms没触发, 那才执行这个事件; 就是这么达到节流的目的的;

我以前记得写过这种的博客 可以看一下:
https://blog.csdn.net/QingWaX...

首先给你点个赞,这个是闭包的优秀使用场景。主要分析下, throttle 这个函数的功能 ;在说之前先把执行流程梳理下

  1. window.addEventListener('scroll', throttle(handle, 1000));这段代码添加了事件监听,拆分下代码
let scrollEventHandle = throttle(handle,1000); // 1
window.addEventListener('scroll',scrollEventHandle); //2

2处的代码,没什么好解释的,就是简单的事件函数。详细的说下1处的代码

throttle 函数的执行,发生了2件事情

  1. 变量 prev 被初始化,也就是 prev = Date.now() ; 也就是说 prev 此时的值是 throttle函数执行的时间
  2. return 一个函数 ;这个函数就是一个 闭包函数 ;这里需要注意,js中关于 scoped的说明,也就是变量的定义,函数的声明,都是有作用域的,而且作用域是可以嵌套的。现在我们改造下 throttle 内部的代码
var throttle = function(func,delay){
  var prev = Date.now(); // 初始化,也就是 throttle 执行的时间,注意这里只是初始化,其实也可以定义一个空变量
  // 上面的变量也可以写为 var prev = 0;
  var scrollEventHandle = function(){
    var context = this;
    var args = arguments;
    var now = Date.now(); // 这个是 scrollEventHandle 执行的时间
    // 判断 scrollEventHandle 执行的时间,和上一个时间直接的间隔
    if(now-prev>=delay){
      func.applay(conetxt,args);
      prev = Date.now(); // 将当前时间作为 下一次需要比较的时间
    }
  }
}

// 注意:
// 这里的 scrollEventHandle 就是返回函数

再简化下代码,把乱七八糟的东西都去掉

function throttle(func,delay){
  let prev = 0; // 这个地方 用 prev = Date.now(); 只是为了初始化
  return function(){
    let now = Date.now();
    if(now-prev>=delay){
       // 执行 func
       func();
       // 并且把这次执行时间,设置为上一次 
       prev = now;
    }
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题