解决频繁性触发事件的操作。是前端的页面性能的优化。
防抖
防抖原理:事件响应函数在一段时间之后才执行,如果在这段时间内再次调用,则需要重新计算执行时间;当预定的时间内没有再次调用该函数,则执行响应逻辑
//防抖函数
function debounce(func, waitTime, immediate) {
let timeout,result;
return function () {
let context = this; //改变执行函数func内部this的指向
let args = arguments; //改变了event的指向
clearTimeout(timeout);
if(immediate){
//立即执行
//timeout有值,则!timeout是false
let callNow = !timeout;
timeout = setTimeout(()=>{
timeout = null; //!null是true
},waitTime);
if(callNow) result = func.apply(context,args);
}else{
//不会立即执行
timeout = setTimeout(()=>{
func.apply(context,args);
},waitTime);
}
return result;
}
}
典型的应用场景:scroll事件滚动触发;搜素框输入查询;表单验证;按钮提交事件;浏览器的窗口缩放,resize事件。
节流
节流原理:如果你持续触发事件,每隔一段时间,只执行一次事件。
//01_时间戳实现
//第一次戳发,最后不会被调用触发函数
function throttle(func, waitTime) {
let context, args;
//之前的时间戳
let old = 0;
return function () {
context = this;
args = arguments;
//获取当前的时间戳
let now = new Date().valueOf();
if (now - old > waitTime) {
//立即执行
func.apply(context, args);
old = now;
}
}
}
//02_定时器实现
//第一次不会触发,最后一次触发
function throttle(func, waitTime) {
let context, args, timeout;
return function () {
context = this;
args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args);
}, waitTime);
}
}
}
//03_结合时间戳和定时器
//第一次不会触发,最后一次立刻结束
function throttle(func, waitTime) {
let context, args, timeout;
let old = 0; //之前的时间戳
let later = function () {
old = new Date().valueOf();
timeout = null;
func.apply(context, args);
}
return function () {
context = this;
args = arguments;
let now = new Date().valueOf();
if (now - old > waitTime) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
func.apply(context, args);
old = now;
} else if (!timeout) {
timeout = setTimeout(later, waitTime);
}
}
}