防抖节流函数理解
#
背景今天在掘金看到一篇文章,想到以前被问到防抖节流函数,让手写一个,当时听都没听过,十分惭愧。当时事后恶补了一下,感觉好像是理解了,实际上闭包都不是十分掌握。最近把js基础又看了一遍,今天无意看到这篇文章,就把自己的理解写一下。
#
防抖函数:debounce#
目的:限制某一事件发生太快,可能是抖动产生才发生这么多次事件,来防止抖动,只运行一次。
#
实例场景:比如说百度的输入框,在输入内容后可能就会直接进行搜索,这里监听输入框的改变事件,当内容发生变化时,就发送ajax请求到后端,调用结果。但是如果用户输入过快,变化次数过多,比如说1s打了5个字,那就没有必要发送5个请求,只需要5个字打完之后,等一段时间,比如500ms,发现输入框还是没有变化,那就认为输入完毕,发送请求。
这个限制条件就是: 一段时间内没有触发这个事件。写了函数如下,关键点如下。
- 实际上是将timer作为闭包,一个私有变量。首先第一次调用这个debounce函数,将触发的事件和间隔事件设置好,会返回一个内部函数,运行那个返回的fn1函数即可。再也没有人能访问函数内的timer变量了,这个timer变量就是闭包。
- 每当事件发生变化时,运行这个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