debounce防抖函数,throttle节流函数

所需知识点

  • 闭包
  1. 闭包的特点:
    (1) 函数内部可以引用外部的参数和变量
    (2) 参数和变量保存在内存中,不会被垃圾回收机制回收(全局变量也会长期保存在内存中)
  2. 缺点:使用不当,容易造成内存泄漏
  3. 全局变量和局部变量是否可以累加?
    (一般情况,全局变量可以累加,而局部变量不能累加,闭包除外)
  4. 很详细 https://segmentfault.com/a/1190000000652891
全局变量的累加:  (全局变量可以累加)
<script>
var a = 1;
function b(){
     a++;
     alert(a);
}
b();            //2
b();            //3
</script>


-----------------------------------------------------------------


局部变量的累加: (局部变量不能累加)
<script>
function b(){
     var a = 1;
     a++;
     alert(a);
}
b();            //2
b();            //2
</script>


-----------------------------------------------------------------


闭包中变量的累加: (闭包可以累加变量)
注意: 因为闭包常驻内存中,所以在执行完后,手动清掉
如下面: y = null; 即时清掉
<script>
function outer(){
        var x=10;
        return function(){             //函数嵌套函数
                x++;
                alert(x);
        }
}
var y = outer();      
y();                 // y函数调用一次,结果为11,相当于outer()();
y();                // y函数调用第二次,结果为12,实现了累加


y = null;       
   
!(注意) 因为y是全局变量,常驻内存,而y依赖于outer(),所以outer也常驻内存,不会被垃圾回收机制清掉

</script>   
  • 闭包在react中的使用(事件和闭包)
  1. 点击事件普通函数
  2. 点击事件闭包

点击事件:普通函数,传参
<div onClick={ (e) => this.common(e, 'anthorParams') }>点击普通函数</div>
common = (e: React.MouseEvent<HTMLDivElement>, anthor: string ): void => {
    console.log(e.target);
    console.log(anthor);
}





点击事件:闭包,传参
<div onClick={ this.closure('name') }>点击闭包函数</div> ----!!注意这里相当于closure('name')()
closure = (name: string) => {
  console.log(name, '1');          -------------------------- 注意:‘1’只会执行一次
  // 比如 let a = 1;
  // 重点:闭包外层变量a能保存在内存中,是因为let a = 1执行一次就没有再从新赋为 1
  // 这也就解释了上面console 1 的时候,为什么只执行了一次
  return (e: React.MouseEvent<HTMLDivElement>) => {  -------- e 在这里获取
    console.log(e.target);
    console.log(name, '2');         ------------------------- 注意:‘2’会多次执行
  };
}

防抖函数 debounce

特点:延时执行,如果在延时的时间内多次触发,则从新计时

延迟执行,设置一个延迟时间a,在事件A发生时,延迟a秒执行事件A,
如果A发生后,a秒内有新的同一事件再次发生,则a从新计时(即又要再延时a秒才会触发事件A)

节流函数 throttle

特点:每隔一段时间,只执行一次

在时间a内,只执行一次函数,多次触发,也只执行一次

来源于网络

竖线的疏密代表事件执行的频繁程度。可以看到,正常情况下,竖线非常密集,函数执行的很频繁。而debounce(函数防抖)则很稀疏,只有当鼠标停止移动时才会执行一次。throttle(函数节流)分布的较为均已,每过一段时间就会执行一次。





debounce函数

原理:
在闭包中设置一个变量来保存setTimeout上一次的状态,有新的输入的时候,清除定时器,再开启一个新的定时器,即重新延迟执行事件

<div onClick={ this.debounce(1000) }>点击debounce函数</div>

debounce = (delay: number) => {
  let timer: any = null; ---- 闭包中的状态保存在内存中,不会被垃圾回收机制清除,所以能保存上一次的状态
  return () => {
    if (timer) {
      window.clearTimeout(timer);  ----- 只要有新的输入,就清掉上一次的定义器,从新执行新的定时器
    }
    timer = window.setTimeout(() => {
      console.log('11111111111');
    }, delay);
  };
}

throttle函数

原理
用闭包设置一个变量开关a,a默认为true,点击后,执行闭包
先判断a的值( 决定是否执行定时器 ),
再把a变为false(目的是为了在规定的延时时间内,再次点击,不再执行定时器 ),
delay秒后,再执行定时器,a变为true,就又会执行定时器了。

<div onClick={ this.throttle(1000) }>点击throttle函数</div>

throttle = (delay: number) => {
  let isRun: boolean = true;
  return () => {
    if (!isRun) {
      return;
    }
    isRun = false;
    window.setTimeout(() => {
      console.log('111111');
      isRun = true;
    }, delay);
  };
}

利用时间戳,实现throttle函数

export const throttle = (fn,wait) => {
    var previous = null; //记录上一次运行的时间
    var timer = null;

    return function(){
        var now = +new Date();
        if ( !previous ) {
            previous = now;
        }
        if(now - previous > wait){
            clearTimeout(timer); -----  这里在时间到后默认会执行一次,如果不想执行,直接return即可
            fn();
            previous = now;   
        }else{
            clearTimeout(timer);
            timer = setTimeout(function(){
                fn();
            },wait);
        }
    }
}


let a = +new Date()
等于
let a = new Date().valueOf()   ----- 返回实例对象距离时间零点对应的毫秒数
也等于
let a = new Date().getTime() 

详细:https://juejin.im/entry/58c0379e44d9040068dc952f
精简:https://segmentfault.com/a/1190000008768202
完美:https://www.jianshu.com/p/f9f6b637fd6c

2019/3/26复习
throttle-Date版本:now-last>delay时,执行函数,小于时不执行,要保证第一次要执行,所以把last初始值设置为0

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id='d'>debounce防抖函数-点击</div>
  <div id='t'>throttle节流函数-点击  setTime版</div>
  <div id='td'>throttle节流函数-点击  Date版本</div>
  <script>
    window.onload = function() {
      // debounce防抖函数
      function debounce(t) {
        let timer;
        return () => {
          window.clearTimeout(timer);
          timer = window.setTimeout(() => {
            console.log('debounce')
          }, t)
        }
      }
      function throttle(t) {
        let isRun = true;
        return () => {
          if (!isRun) {
            return;
          }
          isRun = false;
          window.setTimeout(() => {
            console.log('throttle');
            isRun = true;
          }, t)
        }
      }
      function throttleDate(t) {
        let last = 0;         ----------------- 定义last,保存在内存中,会积累
        return () => {
          let now = + new Date();
          if ( now - last > t) { - 大于delay时间的话,就执行函数,并把last重新赋值到执行完最新的时间
            console.log('throttle-Date');
            last = + new Date();
          }
        }
      }
      //点击防抖函数
      const d = document.getElementById('d');
      d.onclick = debounce(1000);
      // 点击节流函数
      const t = document.getElementById('t');
      t.onclick = throttle(1000);
      // 点击节流函数- Date()
      const td = document.getElementById('td');
      td.onclick = throttleDate(1000);
    }
  </script>
</body>
</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 第二十二章:高级技巧 本章内容: 使用高阶函数 防篡改对象 Yieding Timers 22.1 高级函数 22...
    穿牛仔裤的蚊子阅读 650评论 0 1
  • 前言 最近和前端的小伙伴们,在讨论面试题的时候。谈到了函数防抖和函数节流的应用场景和原理。于是,想深入研究一下两者...
    youthcity阅读 23,499评论 5 78
  • 函数节流 还记得上篇文章中说到的图片懒加载吗?我们在文章的最后实现了一个页面滚动时按需加载图片的方式,即在触发滚动...
    柏丘君阅读 2,833评论 1 19
  • 长久以来,面向对象在 JavaScript 编程范式中占据着主导地位。不过,最近人们对函数式编程的兴趣正在增长。函...
    神刀阅读 454评论 0 0
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,082评论 1 32