防抖与节流
作者:互联网
-
原理:
防抖:在一段时间后执行触发事件,如果在时间内重复触发,则从最后一 次触发开始重新计时,执行。
节流:在一段时间内执行触发事件,如果在时间内重复触发,在时间内也 只触发一次,执行。
-
作用:
本质上是优化高频率执行代码的一种手段。比如:浏览器的
resize
、scroll
、keypress
、mousemove
等事件在触发时会不间断的调用绑定在事件上的回调函数,极大地浪费资源,降低性能。为优化体验,需对这类事件进行调用次数的限制,采用防抖(debounce)
和节流
(throttle)的方式来减少调用频率 -
代码实现:
- 节流:节流可以使用时间戳和定时器的写法
//时间戳写法,如果时间差大于延迟事件会立即执行,停止触发后没有办法再次执行 function throttled1(fn,delay = 500) { //设置延迟delay let oldtime = Date.now() //获取当前时间,并存储为oldtime return function(...args){ let newtime = Date.now() //获取当前时间,并存储newtime if(newtime - oldtime >= delay){ //当时间差大于等于延迟时间时,执行触发的函数 fn.apply(null,args) oldtime = Date.now() //获取当前时间并存储 } } } //定时器写法,delay毫秒后第一次执行,停止触发后事件会再次执行 function throttled2(fn,delay = 500) { let timer = null return function(...args) { if(!timer){ timer = setTime(() => { fn.apply(this,args) timer = null },delay) } } } //定时器和时间戳结合的写法,实现更精确的节流 function throttled(fn,delay) { let timer = null let starttime = Date.now() return function() { let curtime = Date.now() //当前时间 let remaining = delay - (curtime - starttime) //从上次到现在,还剩下多少时间 let context = this let args = arguments clearTimeout(timer) if(remaining <= 0){ fn.apply(context,args) starttime = Date.now() }else{ timer = setTimeout(fn,remaining) } } }
- 防抖:
//简单的实现 function debounce(fn,wait){ let timeout return function(){ let context = this //保存this指向 let args = arguments //拿到event对象 clearTimeout(timeout) timeout = setTimeout(function(){ fn.apply(context,args) },wait) } } //防抖如果需要立即执行,可以加入第三个参数进行判断 function debounce1(fn,wait,immediate) { let timeout return function() { let context = this let args = arguments if(timeout) clearTimeout(timeout) //timeout为undefined if(immediate) { let callNow = !timeout //第一次立即执行,之后只有事件执行后才会再次触发 timeout = setTimeout(function(){ timeout = null },wait) if(callNow){ fn.apply(context,args) } }else{ timeout = setTimeout(function() { fn.apply(context,args) },wait) } } }
-
区别:
相同点:
- 都可以通过
setTimeout
实现 - 目的都是为了降低回调执行频率,节省计算资源
不同点:
- 函数防抖在一段连续的操作结束后,处理回调,利用
clearTimeout
和setTimeout
实现。函数节流在一段连续的操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能。 - 函数防抖关注一定时间连续触发的事件,只在最后一次执行,而函数节流一段时间内只执行一次。
- 都可以通过
参考文献:
https://vue3js.cn/interview/JavaScript/debounce_throttle.html
https://blog.csdn.net/buhuidadaima/article/details/115045476
标签:function,触发,防抖,节流,args,let,timeout,fn 来源: https://www.cnblogs.com/shallow-dreamer/p/16504200.html