防抖(debounce)

防抖就是每触发一次事件,就重新刷新定时器,等定时器延迟走完,执行函数。
比如百度搜索输入框,每输入一个字符,就刷新定时器,直到用户不再输入,则执行查询方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function debounce(fn, delay){
// 维护一个 timer
let timer = null;
return function() {
// 获取函数的作用域和变量
let context = this;
let args = arguments;
if(timer){
clearTimeout(timer);
}
timer = setTimeout(function(){
fn.apply(context, args);
}, delay)
}
}

用防抖函数的时候,一般先赋值给一个变量,执行一次,这样就形成了闭包,多次执行内层函数,timer也只会定义一次

1
const debounceFn = debounce(click,1000)

节流(throttle)

节流是在一段时间内只允许函数执行一次
比如点击一个按钮,一段时间内多次点击,只触发一次
时间戳实现:

1
2
3
4
5
6
7
8
9
10
11
12
var throttle = function(func, delay){
var prev = Date.now();
return function(){
var context = this;
var args = arguments;
var now = Date.now();
if(now-prev>=delay){
func.apply(context,args);
prev = Date.now();
}
}
}

定时器实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var throttle = function(func, delay){
var timer = null;
return function(){
var context = this;
var args = arguments;
if(!timer){
timer = setTimeout(function(){
func.apply(context, args);
timer = null;
},delay);
}
}
}

区别在于,使用时间戳实现的节流函数会在第一次触发事件时立即执行,以后每过 delay 秒之后才执行一次,并且最后一次触发事件不会被执行;而定时器实现的节流函数在第一次触发时不会执行,而是在 delay 秒之后才执行,当最后一次停止触发后,还会再执行一次函数。