js的函数节流和throttle和debounce详解:
同样是实现了一个功能,可能有的效率高,有的效率低,这种现象在高耗能的执行过程中区分就比较明显。
本章节一个比较常用的提高性能的方式,通常叫做"函数节流",下面就通过代码实例对此做一下介绍。
一.函数节流是什么:
在实际编码中,mousemove和resize是使用非常频繁的事件类型(当然还有其他类似事件类型),这样的事件有一个共同的特点,就是在一个普通的操作中,就有可能会在极短的时间内多次执行事件处理函数,会极大的损耗性能,比如resize事件,每次执行通常都会对dom元素进行重新计算,这是非常损耗性能的,何况是频繁的执行,所以在不影响效果的情况下尽可能的减少事件处理函数的执行次数是非常重要的。
二.函数节流的方式:
1.throttle方式:
此单词英文就有"节流"的意思。
更通俗的说就是调节函数执行的频率,控制函数连续两次执行的时间间隔。
下面一个代码:

[JavaScript] 纯文本查看 复制代码运行代码
1
2
3
4
5
6
7
8
9
var timer=null;
$(window).on('resize',function(){
  if(timer){
    clearTimeout(timer)
  }
  timer=setTimeout(function(){
    console.log("蚂蚁部落");
  },400);
});

代码实现了函数节流效果,当调整浏览器窗口大小的时候,"蚂蚁部落"就不会被输出,当调整停止后的400毫秒后才会输出。
上面的方式的的确确实现了函数节流效果,但是感觉有点太狠了,通常我们需要的不是当调整的时候不会输出,而是输出的频率低一点,实现这样的功能,后面会分享一段代码。
2.debounce方式:
此方式和throttle类似,但是它的关注点是函数调用的时间间隔,throttle的关注点是函数执行的时间间隔。
debounce方式对于控制长按键盘暴力输入这种现象非常有效。
三.实例代码:
如果相对函数节流彻底理解掌握,最好完整的分析一段实现此功能的源码。

[JavaScript] 纯文本查看 复制代码运行代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
var throttle = function (fn,delay, immediate, debounce) { 
  var curr = +new Date(),
  last_call = 0,
  last_exec = 0,
  timer = null,
  diff,
  context,
  args,
  exec = function () {
    last_exec = curr;
    fn.apply(context, args);
  };
  return function () {
    curr= +new Date();
    context = this,
    args = arguments,
    diff = curr - (debounce ? last_call : last_exec) - delay;
    clearTimeout(timer);
    if(debounce){
      if(!immediate){
        timer=setTimeout(exec, delay);
      }
      else if(diff >= 0){
        exec();
      }
    }
    else{
      if(diff >= 0){
        exec();
      }
      else if(!immediate){
        timer = setTimeout(exec, -diff);
      }
    }
    last_call = curr;
  }
};

代码虽然将函数对象引用赋值给名为throttle的变量,其实它实现throttle和debounce两种方式,只要调整一下参数即可,下面就对它的实现过程做一下注释。
代码注释:
1.var throttle = function (fn,delay, immediate, debounce) {},此函数能够返回一个可以作为事件处理函数,具有四个参数,fn是一个函数对象,被节流的就是它的执行,delay规定延迟执行的时间,单位是毫秒,immediate是一个布尔值,如果是true,那么相关函数就会立即执行,否则延迟执行,debounce是个布尔值,如果是true,那么就是采用debounce方式。
2.var curr = +new Date(),获取当前时间,是一个时间戳。
3.last_call = 0,声明一个变量并初始化为0,它用来存储上一次试图调用函数的时间。
4.last_exec = 0,声明一个变量并初始化为0,它用来存储上一次函数函数执行的时间。
5.timer = null,声明一个变量,并初始化null,它会存储定时器函数的标识。
6.diff,用来存储时间差。
7.context,用来存储一个上下文对象。
8.args,用来存储函数的参数。
9.exec = function () {
  last_exec = curr;
  fn.apply(context, args);
};声明一个函数,此函数可以获取函数执行的事件,并且执行通过参数传递过来的fn函数。
10.return function () {},返回一个函数,被返回的这个函数就是不断被调用的事件处理函数。
11.curr= +new Date(),获取当前时间对象的时间戳。
12.context = this,将context赋值为this。
13.args = arguments,将参数对象集合赋值给变量args。
14.diff = curr - (debounce ? last_call : last_exec) - delay,这一个很有技巧,可以获取当前时间与延迟时间和上一次被调用的时间或者执行时间的时间差。
15. clearTimeout(timer),停止定时器函数的执行。
16.if(debounce){    if(!immediate){
    timer=setTimeout(exec, delay);
  } 
  else if(diff >= 0){
    exec();
  }
}
如果采用debounce方式,并且采用延迟方式,那么函数会延迟指定的时间再去执行,如果没有采用延迟方式,并且时间差大于等于0(说明延迟时间已到),就执行函数。
17.else{
  if(diff >= 0){
    exec();
  } 
  else if(!immediate){
    timer = setTimeout(exec, -diff);
  }
}
如果采用的是throttle方式,那么就会判断diff 是否大于0,如果大于0就执行函数,第一次执行的时候肯定会大于0,也就是说throttle方式在第一次执行的时候不会有延迟效果。如果不大于零,且采用延迟模式的话,就会延迟执行。
也许看了上面的介绍,对两种方式感觉比较混乱,那么可以参阅函数节流throttle和debounce代码演示一章节,这样就可以比较直观的观察两者的作用和相互间的区别了。

[概念] js的函数节流和throttle和debounce详解的更多相关文章

  1. JS的函数节流(throttle)

    什么是函数节流? 介绍前,先说下背景.在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(其核心就是绑定mousemove),这种事件有一个特点,就是用户不必特地捣乱,他在 ...

  2. (转)JavaScript-性能优化之函数节流(throttle)与函数去抖(debounce)

     JavaScript-性能优化之函数节流(throttle)与函数去抖(debounce)         函数节流,简单地讲,就是让一个函数无法在很短的时间间隔内连续调用,只有当上一次函数执行后过 ...

  3. 函数防抖(Debounce)、函数节流 (Throttle)

    一篇介绍文章:https://zhuanlan.zhihu.com/p/38313717 演示示例:http://demo.nimius.net/debounce_throttle/ 函数防抖(Deb ...

  4. js实现的新闻列表垂直滚动实现详解

    js实现的新闻列表垂直滚动实现详解:新闻列表垂直滚动效果在大量的网站都有应用,有点自然是不言而喻的,首先由于网页的空间有限,使用滚动代码可以使用最小的空间提供更多的信息量,还有让网页有了动态的效果,更 ...

  5. str_replace函数的使用规则和案例详解

    str_replace函数的使用规则和案例详解 str_replace函数的简单调用: <?php $str = '苹果很好吃.'; //请将变量$str中的苹果替换成香蕉 $strg = st ...

  6. main.js index.html与app.vue三者关系详解

    main.js index.html与app.vue三者关系详解 2019年01月23日 11:12:15 Pecodo 阅读数 186   main.js与index.html是nodejs的项目启 ...

  7. js 高程 函数节流 throttle() 分析与优化

    在 js 高程 22.3.3章节 里看到了 函数节流 的概念,觉得给出的代码可以优化,并且概念理解可以清晰些,所以总结如下: 先看 函数节流 的定义,书上原话(斜体表示): 产生原因/适用场景: 浏览 ...

  8. JS魔法堂:函数节流(throttle)与函数去抖(debounce)

    一.前言 以下场景往往由于事件频繁被触发,因而频繁执行DOM操作.资源加载等重行为,导致UI停顿甚至浏览器崩溃. 1. window对象的resize.scroll事件 2. 拖拽时的mousemov ...

  9. JavaScript性能优化之函数节流(throttle)与函数去抖(debounce)

    函数节流,简单地讲,就是让一个函数无法在很短的时间间隔内连续调用,只有当上一次函数执行后过了你规定的时间间隔,才能进行下一次该函数的调用. 函数节流的原理挺简单的,估计大家都想到了,那就是定时器.当我 ...

随机推荐

  1. ZOJ 2856 Happy Life 暴力求解

    因为是Special Judge 的题目,只要输出正确答案即可,不唯一 暴力力求解, 只要每次改变 happiness 值为负的人的符号即可. 如果计算出当前人的 happiness 值为负,那么将其 ...

  2. HDOJ 3635 并查集- 路径压缩,带秩合并

    思路来源:http://blog.csdn.net/niushuai666/article/details/6990421 题目大意: 初始时,有n个龙珠,编号从1到n,分别对应的放在编号从1到n的城 ...

  3. Android进程内存上限

    Android应用程序都是在自己单独的进程中运行.Android为不同类型的进程分配了不同的内存使用上限,如果应用进程使用的内存超过了这个上限,则会抛出Out Of Memory异常,接着进程也被ki ...

  4. Ganglia 权威指南-安装Ganglia过程

    转自于:http://blog.csdn.net/xxd851116/article/details/21527055 http://www.dataguru.cn/article-3816-1.ht ...

  5. InheritableThreadLocal

    InheritableThreadLocal继承自ThreadLocal,但比ThreadLocal多一个特性: 子线程可以继承父亲线程上下文中的信息 但是,有两个点需要注意的: 只有子线程创建之前的 ...

  6. HDOJ 1325 并查集

    跟小希的迷宫基本一样,只是此题是有向图,要注意:1无环 2 只有一个入度为0的结点(根结点), 不存在入度大于1的结点.输入结束条件是两个负数,而不是-1,不然会TLE. #include<st ...

  7. Android4.2以及最新SDK的尝鲜使用

    谷歌已经公布了Android4.2,而且也对应的更新了SDK到4.2.事实上最基本的是谷歌这次帮开发人员把eclipse.ADT.SDK整合 到了一起,我们仅仅须要下载一个ADT Boundle,就能 ...

  8. PHP - Windows安装Pear

    1. 打开命令窗口,切换到php的安装目录,执行以下命令(你也可以添加一个php的环境变量,就不用如此麻烦的切换目录,但是我安装了多个版本的php,所以就没有添加环境变量). 2. 当出现下面这句话时 ...

  9. 幻世(OurDream)2D图形引擎使用教程8——处理操作输入(2)

    声明:本教程版权归Lizcst Software Lab所有,欢迎转载,但是转载必须保留本段声明文字,并注明文章来源:http://blog.csdn.net/kflizcst 谢谢合作! 今天的教程 ...

  10. WCF技术剖析之九:服务代理不能得到及时关闭会有什么后果?

    原文:WCF技术剖析之九:服务代理不能得到及时关闭会有什么后果? 我们想对WCF具有一定了解的人都会知道:在客户端通过服务调用进行服务调用过程中,服务代理应该及时关闭.但是如果服务的代理不等得到及时的 ...