一文教你彻底学会JavaScript手写防抖节流

 更新时间:2022年11月30日 10:04:37   作者:快跑啊小卢_  
其实防抖和节流不仅仅在面试中会让大家手写,在实际项目中也可以起到性能优化的作用,所以还是很有必要掌握的。本文就带大家彻底学会JavaScript手写防抖节流,需要的可以参考一下

前言

  • 前段时间群友说面试的时候老是分不清防抖和节流。
  • 其实防抖和节流不仅仅在面试中会让大家手写,在实际项目中也可以起到性能优化的作用,所以还是很有必要掌握的。
  • 接下来我就用一杯茶的时间带大家彻底学会手写防抖和节流。

防抖

个例子

我们先抛开概念不谈,其实在生活中也有很多防抖的例子:

  • 比如你现在使用的电脑,在不使用后一段时间自动休眠
  • 当你再次使用的时候重新激活,并开始你设置的时间倒计时10分钟
  • 在这10分钟内你继续使用电脑又会重新开始倒计时10分钟
  • 当你最后一次使用电脑并离开时重新倒计时10分钟过去了,电脑就休眠了

这其实这就是防抖的基本概念了~说白了就是在一段时间只执行一次,也就是我们上面的电脑只打开这一次。

我们上面的使用电脑可以理解为触发事件,而与我上面标注的setTimeoutclearTimeout其实就是防抖的主要要素了。

当然上面的是生活中的例子,那我们在我们的日常开发中其实也经常用到,比如我们调整页面的大小,验证表单某个字段是否重复时发生请求次数控制,防止表单多次提交等。

手写防抖

说了这么多,相信大家大概理解了防抖的概念,那我们现在来实现一个防抖吧,假设我们要点击一个按钮新增一条信息,当然我们不希望每次点击都调用接口新增,我们希望多次点击只新增一次,这时候我们该怎么写呢?

首先我们先简单的模拟一个按钮被点击的过程。

// debounce.js
let addBtn=document.getElementById('add')
function addOne(){
  console.log('增加一个')
}
addBtn.addEventListener('click',addOne)

因为我们需要对执行的事件进行处理所以接下来我们需要封装一下addOne函数。

// debounce.js
let addBtn=document.getElementById('add')
function addOne(){
  console.log('增加一个')
}
function debounce(fun){
  return function(){
    fun()
  }
}
addBtn.addEventListener('click',debounce(addOne))

上面我们用闭包处理了一下addOne函数,接下来我们需要添加一个延时器setTimeout来倒计时,当我们点击按钮后过2s再执行。

// debounce.js
function debounce(fun,time){
  return function(){
    setTimeout(()=>{
      fun()
    },time)
  }
}
addBtn.addEventListener('click',debounce(addOne,2000))

现在延时的目的是达到了但是每次点击都会新增一个新的setTimeout而且并不能达到我们多次点击只执行一次的效果。

这时候就需要clearTimeout登场了,我们需要在我们点击了按钮后也就是debounce执行时要先把之前的setTimeout先清除再重新计时。

function debounce(fun,time){
  let timer
  return function(){
    clearTimeout(timer)
    timer=setTimeout(()=>{
      fun()
    },time)
  }
}

现在我们的一个防抖功能就完成了,但是这还没完,如果我们在addOne()打印this会发现我们这样执行的this是指向Window的。

这当然不是我们所希望的,我们需要使用apply来改变this指向,再者就是我们需要考虑到执行函数的参数,因为不同的函数肯定会有不同的参数传入,对于参数我们可以使用arguments处理。

function debounce(fun,time){
  let timer
  return function(){
    clearTimeout(timer)
    let args = arguments
    timer=setTimeout(()=>{
      fun.apply(this,args)
    },time)
  }
}

这样我们的防抖函数就手写完成了,看起来其实也并不难。

总而言之防抖就是在不断的操作中(输入、点击等)最终只执行一次的一种提高性能的方法

节流

举个例子

当然我们生活中也会有很多节流的的例子,不知道大家有没有留意过公园的洒水机:

  • 一般我们会给洒水机设定一个时间假设30min
  • 当距离上次洒水时间未够30min的时候一直保持静止状态
  • 而当到了30min则会触发洒水的事件

  • 这其实也是节流的最基本的概念了,说白了就是在间隔一段时间执行一次
  • 我们上面的洒水可以理解为触发事件,而我们上面标注的其他信息也就只有30min和当前时间,这两个就是节流的主要要素了。
  • 当然上面的是我们的生活中的例子,那我们在我们的日常开发中其实也经常用到,比如我们滚动鼠标滚轮监听滚动条位置,防止按钮多次点击等。

手写节流

说了这么多,相信大家大概理解了节流的概念,那我们现在来实现一个节流吧,假设我们现在要实现一个鼠标滚动打印事件,想让它在3s执行一次,这时候我们该怎么写呢?

首先我们先模拟一个触发事件。

// throttle.js
function scrollTest(){
  console.log('现在我触发了')
}
document.addEventListener('scroll',scrollTest)

接下来我们封装一个节流函数,跟防抖一样我们也需要利用闭包,顺便再加一个参数接收节流时间。

// throttle.js
...
function throttle(fun,time){
  return function(){
    fun()
  }
}
document.addEventListener('scroll',throttle(scrollTest,3000))

因为我们的节流是在一段时间内执行一次也就是说如果两次鼠标滚动的时间间隔未到所设置的时间则不执行

那我们可以记录一下每次滚动的时间戳来进行对比。

// throttle.js
...
function throttle(fun,time){
  let t1=0 //初始时间
  return function(){
    let t2=new Date() //当前时间
    if(t2-t1>time){
      fun()
      t1=t2
    }
  }
}

我们会记录两个时间一个是t1代表初始时间一个是t2代表当前时间,如果当前时间距离上一个时间也就是初始时间大于所设置的time

那我们就可以执行fun()并且把初始时间变更为这一次执行的时间,这样每次我们执行过后t1就变成了上一次执行的时间。

这样我们的一个节流功能就完成了。

// throttle.js
...
function throttle(fun,time){
  let t1=0 //初始时间
  return function(){
    let t2=new Date() //当前时间
    if(t2-t1>time){
      fun()
      t1=t2
    }
  }
}

当然我们也需要像防抖一样改变this指向和接收参数,最后完成后是这样的。

// throttle.js
...
function throttle(fun,time){
  let t1=0 //初始时间
  return function(){
    let t2=new Date() //当前时间
    if(t2-t1>time){
      fun.apply(this,arguments)
      t1=t2
    }
  }
}

至此一个节流函数就手写完成了,是不是也不会很难呢?

总而言之节流就是在一段时间内不断操作而在你规定的时间内只执行一次的一种提高性能的方法

写在最后

  • 首先还是很感谢大家看到这里,这次的文章就分享到这里~
  • 对于防抖和节流一个最主观的判断方法就是:在10s内你疯狂点击一个按钮,如果使用了防抖则会只执行一次,而你使用了节流则会每隔一段时间执行一次,这个时间可以自己来掌控。
  • 当然防抖和节流的变形还是有很多的,根据不同的需求来变换不同的函数但是万变不离其宗,只要你搞懂了上面的方法,其他的就没有问题了。

以上就是一文教你彻底学会JavaScript手写防抖节流的详细内容,更多关于JavaScript防抖节流的资料请关注脚本之家其它相关文章!

相关文章

  • Javascript数组中push方法用法分析

    Javascript数组中push方法用法分析

    这篇文章主要介绍了Javascript数组中push方法用法,结合实例形式分析了javascript中push方法的原理、使用方法与相关注意事项,需要的朋友可以参考下
    2016-10-10
  • javaScript中slice函数用法实例分析

    javaScript中slice函数用法实例分析

    这篇文章主要介绍了javaScript中slice函数用法,较为详细的分析了javascript中slice函数的功能、定义及使用方法,需要的朋友可以参考下
    2015-06-06
  • JS携带参数实现页面跳转功能

    JS携带参数实现页面跳转功能

    这篇文章主要介绍了js携带参数实现页面跳转,实现方法也很简单,方式一是跳转路径携带参数,第二种方法是通过sessionStorage传递,需要的朋友可以参考下
    2022-11-11
  • js模仿hover的具体实现代码

    js模仿hover的具体实现代码

    hover效果,想必大家并不陌生吧,接下来为大家介绍下使用js模仿hover,感兴趣的朋友可以参考下
    2013-12-12
  • JavaScript实现网页版五子棋游戏

    JavaScript实现网页版五子棋游戏

    这篇文章主要为大家详细介绍了JavaScript实现网页版五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • 微信小程序实现按字母排列选择城市功能

    微信小程序实现按字母排列选择城市功能

    这篇文章主要介绍了微信小程序实现按字母排列选择城市功能,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-11-11
  • 微信js-sdk分享功能接口常用逻辑封装示例

    微信js-sdk分享功能接口常用逻辑封装示例

    这篇文章主要介绍了微信js-sdk分享功能接口常用逻辑封装,简单介绍了分享功能接口的功能、逻辑封装与使用方法,需要的朋友可以参考下
    2016-10-10
  • 原生JS实现天气预报

    原生JS实现天气预报

    这篇文章主要为大家详细介绍了原生JS实现天气预报,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06
  • 用js实现轮播图效果

    用js实现轮播图效果

    这篇文章主要为大家详细介绍了用js实现轮播图,播放上一张,下一张,可选取第几张等效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • js实现简单登录功能的实例代码

    js实现简单登录功能的实例代码

    js验证用户身份,登录成功之后等待一定秒数,跳转到操作页面。使用window函数。代码如下
    2013-11-11

最新评论