性能优化之函数防抖与节流

web端性能优化一直是一个重点和难点。今天在看了一篇关于scroll滚动优化性能的文章后,认识了函数的防抖与节流,觉得其用处蛮大的。在这里记录一下。

前言

web端性能优化一直是一个重点和难点。今天在看了一篇关于scroll滚动优化性能的文章后,认识了函数的防抖与节流,觉得其用处蛮大的。在这里记录一下。

应用场景

当我们在频繁操作触发函数方法的情况下,比如下拉加载,移动端手指移动切换动画。都是属于高频触发函数方法,如果在方法中的操作过多,页面就会看起来非常卡顿不流畅。所以我们就要控制函数执行的次数。由此,便衍生了函数的防抖与节流。

防抖

常规操作下我们会这样写:

1
2
3
4
var i = 0;
window.addEventListener('scroll', function(){
console.log(i++);
}, false)

以上写法便是个高频操作,如果执行的操作是DOM操作,会频繁的触发页面重绘,帧率降低,影响性能。所以我们要控制他执行的次数,把一连串的触发合并成一次,即滚动事件结束才触发。举个栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function debounce(func, wait) {
var timeout;
return function() {
// 每次触发 scroll handler 时先清除定时器
clearTimeout(timeout);
// 指定 xx ms 后触发真正想进行的操作 handler
timeout = setTimeout(func, wait);
};
};

// 实际想绑定在 scroll 事件上的 handler
function realFunc(){
console.log("Success");
}

// 采用了防抖动
window.addEventListener('scroll',debounce(realFunc,500));

只要触发间隔低于500ms,就不会连续触发,即在最后一次触发scroll事件500ms后才去响应执行函数。这便是防抖。

节流

如果你试了防抖的方法,会发现他在最后一次触发滚动都才去执行方法,如果我一直下拉滚动,中间却没有执行加载资源。这很明显是不正确的。我们希望在频繁滚动中,也能间隔性的执行加载方法,由此,便产生了节流——至少在xx时间内执行一次,与防抖相比,节流多了一个mustRun参数,即mustRun时间内必须执行一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function throttle(fn, wait, mustRun) {
var timeout,
startTime = new Date();
console.log(startTime) //只在页面初始化时执行一次,后续滚动都不会触发这里
return function () {
var context = this;
var args = arguments, curTime = new Date();
clearTimeout(timeout);
if(curTime - startTime >= mustRun){
fn.call(context, args);
startTime = curTime;
} else {
timeout = setTimeout(fn,wait);
}
}
}
function done() {
console.log('success');
}
window.addEventListener('scroll', throttle(done, 500, 1000), false);

以上方法,会在滚动频率高于500ms时,保证每1000ms执行一次方法。

(完!)