# 防抖 debounce
函数防抖就是在函数需要频繁触发的情况下,只有足够的空闲时间,才执行一次。
典型应用
- 百度搜索框在输入稍有停顿时才更新推荐热词。
- 拖拽
function debounce(handler, delay){
delay = delay || 300;
var timer = null;
return function(){
var _self = this,
_args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
handler.apply(_self, _args);
}, delay);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
防抖函数为什么要记录this
和参数的例子:
// 频繁触发时,清楚对应的定时器,然后再开一个定时器,delay秒后执行
function debounce(handler, delay){
delay = delay || 300;
var timer = null;
return function(){
var _self = this,
_args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
handler.apply(_self, _args);
}, delay);
}
}
// 不希望被频繁调用的函数
function add(counterName) {
console.log(counterName + ": " + this.index ++);
}
// 需要的上下文对象
let counter = {
index: 0
}
// 防抖的自增函数,绑定上下文对象counter
let db_add = debounce(add, 10).bind(counter)
// 每隔500ms频繁调用3次自增函数,但因为防抖的存在,这3次内只调用一次
setInterval(function() {
db_add("someCounter1");
db_add("someCounter2");
db_add("someCounter3");
}, 500)
/**
* 预期效果:
*
* 每隔500ms,输出一个自增的数
* 即打印:
someCounter3: 0
someCounter3: 1
someCounter3: 2
someCounter3: 3
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 节流 throttle
一个函数只有在大于执行周期时才执行,周期内调用不执行。好像水滴积攒到一定程度才会触发一次下落一样。
典型应用:
- 抢券时疯狂点击,既要限制次数,又要保证先点先发出请求
- 窗口调整
- 页面滚动
function throttle(handler, wait){
wait = wait || 300;
var lastTime = 0;
return function(){
var _self = this,
_args = arguments;
var nowTime = new Date().getTime();
if((nowTime - lastTime) > wait){
handler.apply(_self, _args);
lastTime = nowTime;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
复杂但好用版:
function throttle(fn, interval, context, firstTime) {
let timer;
firstTime = typeof firstTime !== 'undefined' ? firstTime : true;
return function() {
let args = arguments;
let __me = this;
if (typeof context !== 'undefined') {
__me = context;
}
if (firstTime) {
fn.apply(__me, args);
return (firstTime = false);
}
if (timer) {
return false;
}
timer = setTimeout(function() {
clearTimeout(timer);
timer = null;
fn.apply(__me, args);
}, interval);
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 节流与防抖的本质
以闭包的形式存在,通过对事件对应的回调函数进行包裹、以自由变量的形式缓存时间信息,最后用定时器或时间差来控制事件的触发频率。