Skip to main content

防抖节流函数理解

背景#

今天在掘金看到一篇文章,想到以前被问到防抖节流函数,让手写一个,当时听都没听过,十分惭愧。当时事后恶补了一下,感觉好像是理解了,实际上闭包都不是十分掌握。最近把js基础又看了一遍,今天无意看到这篇文章,就把自己的理解写一下。

防抖函数:debounce#

目的:#

限制某一事件发生太快,可能是抖动产生才发生这么多次事件,来防止抖动,只运行一次。

实例场景:#

比如说百度的输入框,在输入内容后可能就会直接进行搜索,这里监听输入框的改变事件,当内容发生变化时,就发送ajax请求到后端,调用结果。但是如果用户输入过快,变化次数过多,比如说1s打了5个字,那就没有必要发送5个请求,只需要5个字打完之后,等一段时间,比如500ms,发现输入框还是没有变化,那就认为输入完毕,发送请求。


这个限制条件就是: 一段时间内没有触发这个事件。写了函数如下,关键点如下。

  1. 实际上是将timer作为闭包,一个私有变量。首先第一次调用这个debounce函数,将触发的事件和间隔事件设置好,会返回一个内部函数,运行那个返回的fn1函数即可。再也没有人能访问函数内的timer变量了,这个timer变量就是闭包。
  2. 每当事件发生变化时,运行这个fn1函数,首先会设置一个定时器,准备运行那个期望的回调函数fn,假如在间隔时间内再次触发了事件,进入了函数,则清除掉定时器timer,重新设置新的timer。直到满足间隔时间,运行时间结束后,由定时器内部的回调清除掉timer。

节流和防抖差不多,看到一个有意思的理解:
防抖:不冷静的决定,最后一次才能一锤定音。
节流:技能的cd,要间隔一段时间才能再次使用。
下面是防抖和节流的代码:

var debounce = function(fn, delay=200) {    let timer;    return function() {        let context = this;        let args = arguments;        if(timer) clearTimeout(timer);        timer = setTimeout( ()=>{            fn.call(context, args);            timer = null;        }, delay);    }}
var fn1 = debounce( ()=> console.log("I am here!"), 500);
for( let i=0; i<100; i++) {    fn1();}

//时间戳版本var throttle = function(fn, delay) {    let lastTime = 0;    return function() {        let now = Data.now();        let context = this;        let args = arguments;        if(now - lastTime > delay) {            fn.call(context, args);            lastTime = Data.now();        }    }}
var fn2 = throttle(()=>{console.log("This is 节流函数")}, 1000);fn2();

//定时器版本,但是要等定时器设置的时间才可以运行第一次var throttle2 = function(fn, delay) {    let timer;    return function() {        let context = this;        let args = arguments;        if(!timer) {            timer = setTimeout(() => {                        fn.call(context, args);                        timer = null;                    }, delay);        }    }}

以上就是我对于防抖和节流的理解了,今晚想要试着跑第一次半马~

2019.10.18 written by: LRQ