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. Codeforces 482 - Diverse Permutation 构造题

    这是一道蛮基础的构造题. - k         +(k - 1)      -(k - 2) 1 + k ,    1 ,         k ,             2,    ....... ...

  2. 如何使用银联卡充值美元到BTC-E以及比特币搬砖教程

    1,名词解释 搬砖:就是在价格低的平台买入比特币,然后转移到价格高的平台卖出, 一般而言,BTC-E是国外三大比特币交易所中比特币单价最低的一个站,因为其需要用美元充值,相对不方便.之前国内比特币价格 ...

  3. android4.4组件分析--service组件

    6       Service 6.1            service介绍 6.1.1.            基本介绍 Service是Android四大组件之中的一个(其余的是activit ...

  4. Python笔记之基本的语法

    1 变量和赋值 Python是动态类型语言,不须要预先声明变量的类型.变量的类型在赋值的那一刻被初始化. Python变量名是大写和小写敏感的,即"cAsE"与"CaSe ...

  5. linux 内核代码精简

    #为了提高性能,文件系统一般都是以 relatime形式挂载进来的,见:/etc/fstab #更新一下mtime,这样,编译过程中用到的文件的atime都会被更新 find . -exec touc ...

  6. ubuntu apt-get 遇到的问题

    装软件的时候总是提示dpkg: warning: files list file for package `*****' missing, assuming package has no files ...

  7. 交换机Trunk端口配置

    本文为转发,简单明了,我喜欢. Trunk端口的配置步骤如下: 一 组网需求: 1.SwitchA与SwitchB用trunk互连,相同VLAN的PC之间可以互访,不同VLAN的PC之间禁止互访: 2 ...

  8. linux eclipse中运行android AVD 错误

    当使用android的AVD时提示以下错误: Starting emulator for AVD 'NexusOne' ERROR: 32-bit Linux Android emulator bin ...

  9. linux popen函数

    描述 popen() 函数 用 创建管道 的 方式启动一个 进程, 并调用 shell. 因为 管道是被定义成单向的, 所以 type 参数 只能定义成 只读或者 只写, 不能是 两者同时, 结果流也 ...

  10. Unix时间戳 POSIX时间 Unix时间

    Unix时间戳(Unix timestamp),或称Unix时间(Unix time).POSIX时间(POSIX time),是一种时间表示方式,定义为从格林威治时间1970年01月01日00时00 ...