防抖与节流
Jonnzer Lv4

1.防抖

✨ 业务场景:你尽管触发事件,但是我一定在事件触发 n 秒后才执行。
如果你在一个事件触发的 n 秒内又触发了这个事件,那我就以新的事件的时间为准,n 秒后才执行,
总之,就是要等你触发完事件 n 秒内不再触发事件,我才执行.
简单的说法是,取决于上次没操作后,delay时间后执行。

👍适用场景:input的格式验证、提交按钮的点击事件(触发频不那么高)

介绍三个版本:

1指定this

1
2
3
4
5
6
7
function debounce(func, wait) {
var timeout;
return function() {
clearTimeout(timeout)
timeout = setTimeout(func,wait) // 保持只是一个定时器
}
}

2 this指向 && 指定传参(比如event

1
2
3
4
5
6
7
8
9
10
11
12
13
function debounce(func, wait) {
var timeout;
// console.log(this) // 这里的时候指向window
return function() {
var context = this // 这里的时候指向btn 关键是缓存这时候的this
var args = arguments
clearTimeout(timeout)
timeout = setTimeout(function() {
//没绑定context时,这里this指向window
func.apply(context,args)
}, wait)
}
}

3 this指向 && 指定传参 && 立即执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this
var args = arguments
if (timeout) { clearTimeout(timeout) }
if (immediate) { // 立即执行
// timeout有值的情况下,改为延时
var callNow = !timeout
timeout = setTimeout(function () {
timeout = null
},wait)
if (callNow) { func.apply(context,args) }
// 跑完立即执行,永远都会执行上面的timeout = null,
// 然后下一次进入判断callNow时,又会是立即执行。
} else {
timeout = setTimeout(function () {
func.apply(context,args)
},wait)
}
}
}

2.节流

按指定的delay执行
👍 适用场景:(触发频高)resize, touchmove, mousemove, scroll 动画场景

下面介绍两个版本:

✨ 使用时间戳

使用时间戳,当触发事件的时候,我们取出当前的时间戳,
然后减去之前的时间戳(最一开始值设为 0 ),
如果大于设置的时间周期,就执行函数,然后更新时间戳为当前的时间戳,
如果小于,就不执行。

第一下会立刻执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// +new Date() 将会调用 Date.prototype 上的 valueOf() 方法,
// Date.prototype.value方法等同于Date.prototype.getTime()
function throttle(func, wait) {
var previous = 0
return function() {
var now = +new Date()
const args = arguments
const context = this
if ((now - previous) > wait) {
func.apply(context,args)
previous = now
}
}
}

✨ 使用定时器

当触发事件的时候,我们设置一个定时器,
再触发事件的时候,如果定时器存在,就不执行,
直到定时器执行,然后执行函数,
清空定时器,
这样就可以设置下个定时器。

第一下会延时执行
1
2
3
4
5
6
7
8
9
10
11
12
13
function throttle(func, wait) {
var timeout;
return function () {
const context = this
const args = arguments
if (!timeout) {
timeout = setTimeout(function () {
timeout = null
func.apply(context, args)
}, wait)
}
}
}

3.两者的关联与区别

两者都有控制触发的次数,防抖控制的更厉害,节流是降低频率
假设无限次触发:防抖函数永远不会真正执行,节流函数则会按照间隔时间执行。

参考链接:
专栏
mqyqingfeng issue

  • 本文标题:防抖与节流
  • 本文作者:Jonnzer
  • 创建时间:2019-12-03 10:44:39
  • 本文链接:https://jonnzer.github.io/2019/12/03/防抖与节流/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论