函数防抖与函数节流

此两种函数在平常的开发中不一定会遇到,但确实面试时经常遇到的问题,所以作为一名前端工程师还是需要掌握的。

1. 函数防抖

在用户注册时验证用户名是否被占用,很多网站为了提升用户体验,不再等待用户点击提交按钮才去校验输入内容,而是输入框有输入内容时就校验。但是这样实现会增加浏览器请求服务器的压力,所以此时函数防抖就派上用场了。函数防抖:顾名思义,就是等一系列输入操作都完成之后,一段时间内没有输入动作,再去请求服务器进行校验。具体实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
var timer = null;   // 此处一定要是全局变量,至少不能在每次调用debounce的时候重新声明

function debounce(fn, delay) {
var context = this;
var args = arguments;
return function() {
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay)
}
}

2. 函数节流

以判断页面滚动是否到底为例,一般的做法是监听window的scroll事件。但是鼠标滚动是连续的,会触发多次事件,消耗浏览器资源。此时函数节流就有了用武之地。函数节流:顾名思义,就是在将连续执行的事件每隔一段时间执行一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 实现1
function throttle(fn, delay) {
let canRun = true;
let context = this;
let args = arguments;
return function () {
if (!canRun) {
return;
}
setTimeout(function () {
fn.apply(context, args)
canRun = true;
}, delay)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 实现2
function throttle(fn, delay) {
var context = this;
var args = arguments;
var timer = null;
return function () {
if (!timer) {
timer = setTimeout(function () {
fn.apply(context, args);
timer = null;
}, delay)
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 实现3
function throttle(fn, delay) {
var prev = null;
var timer = null;

return function () {
var now = new Date();
if (!prev) {
prev = now;
}
if (now - prev > delay) {
clearTimeout(timer);
fn();
prev = now;
} else {
clearTimeout(timer);
timer = setTimeout(function () {
fn();
}, delay);
}
}
}