一、函数防抖
- 对于在事件被触发n秒后再执行的回调:延迟回调
- 如果在这n秒内再触发事件、重新开始计时
防抖常见案例:ajax的请求与提交数据(手机端下拉刷新)、输入的过程中校验合法性
// 需求:一个按钮,点击后1s打印1出来
var oBtn = document.getElementsByTagName('button')[0];
var t = null;
oBtn.onclick = function() {
clearTimeout(t);
t = setTimeout(() => {
console.log(1);
}, 1000);
}
/*
这个写法存在的问题:
1. 污染全局
2. 初次触发事件时,会延迟执行
*/
1、debounce防抖函数实现
/**
* @fn:目标函数
* @time:延迟时间
* @triggleNow:初次是否需要触发
* true:首次不进行防抖处理 false:首次需要防抖处理
*/
function debounce(fn, time, triggleNow) {
var t = null;
var debounced = function() {
var _self = this,
args = arguments;
if(t) {
clearTimeout(t);
}
if(triggleNow) {
// 判断一个是否执行
var exec = !t;
// 要满足第一个需求:要延迟
t = setTimeout(function() { // 在time时间内再次触发事件 t是一个id值
// 防抖核心原理:time内频繁触发事件,计时器会重新开始计时
t = null; // 为了exec还是true
}, time);
// 第一次近来直接走 exec
if(exec) {
fn.apply(_self, args);
}
}else {
// 直接延迟
t = setTimeout(function() {
fn.apply(_self, args);
}, time);
}
}
// 强制取消防抖
debounced.remove = function() {
clearTimeout(t);
t = null;
}
return debounced;
}
所谓防抖,就是考虑两种情况
- triggleNow是true(首次不进行防抖处理)
- 还是 false
- 总结:
- 是否首次延迟执行
- n秒之内,触发事件不执行事件处理函数(n秒之内频繁触发事件,计时器会频繁重新开始计时)
2、防抖案例
- 获取ajax数据:首次获取ajax数据不需要防抖(triggleNow为true)
- 监听用户输入的合法性:首次监听也需要防抖(triggleNow为false)
二、节流函数
输入验证也可以用节流来做
- 函数节流:事件被触发、n秒之内只执行一次事件处理函数
function throttle(fn, delay) {
var t = null,
begin = new Date().getTime();
return function() {
var _self = this,
args = arguments,
cur = new Date().getTime();
clearTimeout(t);
if(cur - begin >= delay) {
fn.apply(_self, args);
begin = cur;
}else {
t = setTimeout(function() {
fn.apply(_self, args);
}, delay);
}
}
}