写点什么

JavaScript- 防抖

  • 2022-11-09
    广东
  • 本文字数:1338 字

    阅读完需:约 4 分钟

JavaScript-防抖

前言

说到防抖,很多人会不明白是什么意思?举个简单的例子,在游戏里,防抖就类似王者荣耀里的回城,被打断了就得重新回城;在代码里,防抖就是触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间。我们如何实现防抖呢?

防抖

防抖主要是围绕触发事件setTimeoutclearTimeout 这三个功能来进行防抖操作的


假设为了防止用户多次点击操作按钮,因此我们需要进行防抖操作,前面说到触发事件,因此我们用到 addEventListener,按钮被点击后就会触发 addEventListener 里面的函数,我们需要延迟执行 addEventListener 里面的函数,就需要用到 setTimeout 了,仅仅延迟执行还不够,用户继续点击按钮的话需要清除延时,还得加入 clearTimeout



举个简单的案例演示,新建一个按钮,在 js 里获取这个按钮,创建一个函数,这个函数表示事件触发要执行的任务,最后给按钮添加事件监听,点击一下按钮就会有正常的监听效果


<button>点击</button><script>    const button=document.querySelector('button')
function btnClick(){ console.log('点击'); }
button.addEventListener('click',btnClick)</script>
复制代码


接下来要进行防抖设置了,创建一个防抖函数并把事件触发执行的任务设置为这个防抖函数,明显要在防抖函数里执行原来的任务,这就需要为防抖函数设置一个参数,并且执行这个参数


function debounce(func){  func()}button.addEventListener('click',debounce(btnClick))
复制代码



但是这样在定义监听函数的时候就直接执行了函数,这是防抖的第一个难点,为了解决我们需要用高级函数,就是在函数里返回函数,刷新后就没有错误了


function debounce(func){  return function(){    func()  }}
复制代码


接下来就可以设置延时了,在返回函数里加一个 setTimeout,在里面执行 btnClick 这个函数,同时也在防抖函数里新增第二个参数,作为延时的事件,延时效果就出来了


function debounce(func,delay){  return function(){    setTimeout(() => {      func()    }, delay);  }}
button.addEventListener('click',debounce(btnClick,1000))
复制代码


有延时就有清除延时,在定义监听时间的时候就定义一个变量,所有独立的执行函数都能访问到这个变量,而且这个变量只创建了一次,只需要不断给变量赋值进行延时,然后在返回函数里清除延时


function debounce(func,delay){  let timer  return function(){    clearTimeout(timer)    timer=setTimeout(() => {      func()    }, delay);  }}
复制代码



连续点击多次控制台也只显示一条信息,看似防抖函数实现了,但是还有一个地方被我们忽略了


function btnClick(){  console.log('点击');  console.log(this);}
复制代码



在事件触发要执行的任务的函数里打印 this,看看 this 的指向,this 的指向应该是指向 button 的但是控制台显示指向了 window。因为回调的原因,运行时已经在 window 下了,所以我们要在延时之前把 this 保存下来,此时 this 指向按钮,在延时中用 call 来绑定这个 this 给事件触发要执行的任务的函数,最后控制台打印正确


function debounce(func,delay){  let timer  return function(){    let context=this    clearTimeout(timer)    timer=setTimeout(() => {      func.call(context)    }, delay);  }}
复制代码



发布于: 刚刚阅读数: 3
用户头像

你若毁我天堂,我必戳你脊梁 2022-11-01 加入

还未添加个人简介

评论

发布
暂无评论
JavaScript-防抖_JavaScript_格斗家不爱在外太空沉思_InfoQ写作社区