在日常前端开发中我们经常会遇到一些频繁的事件触发,例如: window中的
resize、scroll;mousedown、mousemove;keyup、keydowm
函数防抖
n秒后再执行执行该事件,如果在该事件触发的n秒内它又再一次触发了这个事件,那就以新时间的时间为准,n秒后才执行
函数节流
n秒内只执行一次,如果在n秒内持续重复触发该事件,只有一次生效,即只执行一次事件
如何实现
防抖
** 简单实现 **
function debounce(func, wait) {
let timeout;
return function() {
//保存地址指向
let context = this;
//拿到event对象
let args = arguments;
clearTimeout(timeout)
timeout = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
** 如果需要立即执行,可加入第三个参数用于判断 **
function debounce(func, wait, immediate) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout); // timeout 不为null
if (immediate) {
let callNow = !timeout; // 第一次会立即执行,以后只有事件执行后才会再次触发
timeout = setTimeout(function () {
timeout = null;
}, wait)
if (callNow) {
func.apply(context, args)
}
}
else {
timeout = setTimeout(function () {
func.apply(context, args)
}, wait);
}
}
}
节流
** 使用时间戳 **
function throttle1(func, wait) {
var context, args;
var previous = 0;
return function() {
var now = +new Date();
context = this;
args = arguments;
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}
}
** 使用定时器 **
function throttle2() {
var timeout;
var previous = 0;
return function() {
context = this;
args = arguments;
if (!timeout) {
timeout = setTime(function() {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
** 二者结合版 **
function throttled3() {
let timer = null;
let starttime = Date.now();
return function() {
//当前时间
let curTime = Date.now();
//从上一次到现在,还剩下多少多余时间
let remain = delay - (curTime - startTime);
let context = this;
let args = arguments;
clearTime(timer);
if (remaining <= 0) {
fn.apply(context, args);
startTime = Date.now();
}
else {
timer = setTimeout(fn, remaining)
}
}
}
** 总结**
- 二者都可以通过使用
setTimeout 实现
- 目的都是,降低回调执行频率。节省计算资源
** 区别**
- 函数防抖,在一段连续操作结束后,处理回调,利用
clearTimeout和 setTimeout实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能
- 函数防抖关注一定时间连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次
** 应用场景**
防抖在连续的事件,只需触发一次回调的场景有:
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求
- 手机号、邮箱验证输入检测
- 窗口大小
resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
节流在间隔一段时间执行一次回调的场景有:
-
滚动加载,加载更多或滚到底部监听
-
搜索框,搜索联想功能
参考文章:
# 什么是防抖和节流
js专题