
在事件被触发n秒后再执行回调函数,如果在这n秒内又被触发,则重新计时。(就像王者荣耀回城一样,只有在不被别人打断n秒后才能回去, 否则这期间有人打断就会重新计时。)
指触发事件后在规定时间内回调函数只能执行一次,如果在规定时间内又触发了该事件,则会重新开始算规定时间。
简单总结就是 延时执行 最后一次触发。
理解一下上图,用户多次频繁的触发某个事件,用户第一次触发事件后开始计时,在未满足时间间隔时就进行了第二次触发,那么将第一次触发的事件清除() ,对第二次触发的事件重新开始计时;在未满足时间间隔时就进行了第三次触发,那么将第二次触发的事件清除,对第三次触发的事件重新开始计时,在满足时间间隔的一段时间内,用户未触发事件,则执行第三次触发的事件(即) 。同样的,上述过程完成后,用户又第一次触发了这个事件,开始计时,在未满足时间间隔时,用户第二次触发事件,那么将第一次触发的事件清除,对第二次触发的事件重新开始计时;在满足时间间隔的一段时间内,用户未触发事件,则执行第二次触发的事件(即最后一次) 。
先了解定时器的用法:
需要借助setTimeout(JavaScript 函数, 等待的毫秒数) 函数(也称为定时器),来规定多少时间后执行 触发的事件 或 调用的函数。
clearTimeout() 方法可取消由 setTimeout() 方法设置的定时操作。clearTimeout() 方法的参数必须是由 setTimeout() 返回的 ID 值。
从上述过程,我们对代码要做的事进行分析:
通过定时器将回调函数进行延时.如果在规定时间内继续回调,发现存在之前的定时器,则将该定时器清除,并重新设置定时器.这里有个细节,就是后面所有的回调函数都要能访问到之前设置的定时器,这时就需要用到闭包(详见后面提到的)
注意点:
1.为了使后面所有的回调函数都能访问到之前设置的定时器,使用闭包定义局部变量timer
:闭包形成的两个条件:1. 函数可以访问声明该函数的作用域上的变量 2. 函数的调用不在其声明作用域内。
:函数内部能访问到外部上级作用域的变量是因为作用域链的存在。从函数外部能访问函数内部的变量就是闭包。
: 什么是闭包?闭包是由函数以及声明该函数的词法环境组合而成的。该环境包含了这个闭包创建时作用域内的任何局部变量。
代码第二行在外层定义了变量timer,并在内层函数使用了这个变量;同时debounce函数会返回一个fn功能版函数,当返回的这个fn功能版函数调用时,debounce函数已经执行完毕,但在功能函数中任然可以访问定义在debounce函数中的局部变量timer,也就是从debounce函数外部能访问debounce函数内部的变量,这就形成了闭包。以使后面所有的回调函数,都能访问到之前设置的定时器返回的ID。
2.最后一次调用函数,不会被清除。
在函数第一次被触发时,timer=null, 不会执行clearTimeout(timer);在规定的时间间隔内,进行第二次调用,将会在第一次定时器的回调函数还未执行时,就将其取消(即清除),对第二次触发进行重新计时,若在等待完规定的毫秒数后,没有新的触发,那么第二次的定时器回调函数正常执行。但在用户最后一次触发函数后,后续再也不会执行clearTimeout(timer),所以最后一次定义的定时器的回调函数会正常执行。
3.不要改变fn的原this指向(也即执行上下文的this属性), 改变this指向为调用debounce所指的对象
- 我们原本的动作是执行fn(), 假设此时fn内部的this指向thisFn。 将fn通过debounce函数包装以后,我们得到了一个新的功能函数myFn, 现在的动作变成了myFn()。并且在myFn内部去执行fn()。那么myFn内部的this指向thisFn,而fn内部的this指向window (默认绑定) ,这就改变了fn原本的this指向,是不合理的,我们不应该改变fn的功能,而是加强fn的功能。所以应该在myFn内部去执行fn()时,为fn绑定当前myFn的this指向。
- 并且在setTimeout的回调中调用fn时, 要考虑到setTimeout是宏任务,在当前同步代码结束后,才会调用setTimeout的回调函数,会造成this丢失,所以应该在setTimeout回调内部去执行fn()时,为fn绑定当前myFn的this指向。由于setTimeout回调是箭头函数,所以setTimeout回调内部的this就是返回的myFn的this指向。
防抖分为两种:
- 1)非立即执行版:事件触发->延时->执行回调函数;如果在延时中,继续触发事件,则会重新进行延时.在延时结束后执行回调函数.常见例子:就是input搜索框,客户输完过一会就会自动搜索
- 2)立即执行版:事件触发->执行回调函数->延时;如果在延时中,继续触发事件,则会重新进行延时.在延时结束后,并不会执行回调函数.常见例子:就是对于按钮防点击.例如点赞,心标,收藏等有立即反馈的按钮.
带有立即执行选项的防抖函数:
立即执行版防抖函数:

函数防抖: 将几次操作合并为一此操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。
两个条件: 1,如果客户连续的操作会导致频繁的事件回调(可能引起页面卡顿). 2,客户只关心"最后一次"操作(也可以理解为停止连续操作后)所返回的结果. 例如:
- search搜索联想,用户在不断输入值时,用防抖来节约请求资源。
- 不断的调整浏览器窗口大小会不断的触发resize事件,用防抖来让其只触发一次。
- 按钮点击:收藏,点赞,心标等
链接:juejin.cn/post/…
链接:mp.weixin..com/s/Vkshf-nED…
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/13988.html