带你轻松实现防抖、节流。

305 阅读4分钟

一、防抖

防抖的原理:当持续触发一个事件的时候,在规定时间内没有继续触发事件的时候,则会回调我们传递进去的函数,如果在该过程中一直有触发,则会重新计时。 辅助理解:当我们坐电梯的时候,当一直有人进电梯的时候,电梯门不会关闭,当没人进电梯了,过一段时间电梯门就会自动关闭(电梯关门相当于我们传入的回调函数开始执行)。

1.1 实现基本的防抖函数

我们首先定义一个debounce的函数,在这之前我们要考虑该函数接收什么参数,第一个参数应该是我们要回调的函数,第二个参数应该是延迟的时间。debounce的核心是要考虑什么时候去执行我们传递过来的回调函数,因此可以根据我们传递过来的延迟时间,开启一个定时器来执行我们传递过来的回调函数。

code.png 这样确实可以实现在2秒后才执行回调函数,但是该回调函数一直有被执行,显然是不对的,就比如电梯门进来一个人就关门,在进来一个人又关。

code.png

因此我们要想到当第二个人进来的时候,电梯门不应该关门,而是让他重新计算关门的时间。

code.png 这里用到了闭包引入外部的自由变量,当timer有值的情况下,清除定时器他就不会执行了而是去重新计算时间,因此我们就实现了一个简单的防抖函数。

1.2 this的指向问题

当我们打印input的this.value的时候,控制台输出的是undefine的,因为此时的this隐式绑定的this,是window在调用该回调函数,相当于window.fn(),因此我们要使用apply来改变他的this执行。

code.png

控制台正确的输出input的值。

1.3 不要滥用箭头函数

注意!!!!!!!不要滥用箭头函数:const _debounce函数不可以赋值给他箭头函数,因为箭头函数this是不绑定的,这个本质是input的元素在调用该函数,如果换成了箭头函数这种绑定失效,他会向上查找this绑定的元素。。。

1.4 参数的问题

有的时候我们需要用到input中的event对象,但是我们上面代码是没有接收参数的,但是我们也不知道用户会传递几个参数过来,因此我们用到es6的剩余参数(可以正确打印event对象)。

code.png

1.5 停止执行debounce

当我们在输入框输入内容,等待回调函数执行中,我们假如此时点击了取消按钮,我们应该取消回调函数的执行。本质就是取消定时器,让他不要往下执行。

code.png

可以看到当我点该按钮后,控制台并没有输出我新输入的内容。 code.png

二、节流

节流的原理:在规定时间内只会执行一次,比如5秒的时候执行一次,到了78秒之后不会执行,到了10秒的时候才会执行第二次,只有大于间隔的时间在去执行第二次。 辅助理解:当我们在玩游戏的时候,你的普通攻击的速度5秒内射出几个子弹,无论你点击得多快,他不会因为你点击得快而输出的子弹就多。

2.1 实现基本的节流函数

我们首先定义一个throttle函数,跟上面一样我们要考虑接收什么参数,第一个应该是我们回调的函数,第二个应该是间隔的时间。throttle的核心是怎么让他在我们规定的间隔时间去执行函数。因此我们可以根据我们根据现在的时间、隔间的时间、当前的时间推到出只有大于间隔的时间才会再一次执行回调函数。 //获取当前的时间 const nowTime = new Date.getTime() //开始的时间 const startTime = 0 //const awaitTime = 我们自定决定的时间 - (现在的时间 - 开始的时间) //只有大于我们间隔的时间才会去执行回调函数 因此awaitTime一定要是小于等于0的

code.png

这样就实现了一个基本的节流函数了~ 跟上面的防抖函数注意事项玉一样,这里我就不在继续赘述了。