介绍防抖节流的原理,以及应用,Javascript实现。
1.防抖:
。原理:在事件被触发N秒以后在执行回调,如果在这N秒之内再次触发,则重新计算。
。使用场景:
。按钮提交场景:防止多次提交按钮,只执行最后一次。
。搜索框联想场景:防止连续发送请求,只发送N秒后的最后一次。
简易版实现
const btnEle = document.querySelector(".btn");
btnEle.onclick = debounce(function () { console.log("我执行了最后一次")}, 3000)
//防抖函数
//创建一个函数:接受一个执行函数,多少秒执行
function debounce(func, wait) {
console.log("第一次执行");
//定义有效时间
let timeout;
return function () {
console.log("我被点击了1。")
//获取当前对象
const context = this;
// 当前参数
const args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function () {
func.apply(context, args);
}, wait)
}
。立即执行版本
const btnEle = document.querySelector(".btn");
btnEle.onclick = debounce(function () { console.log(123) }, 3000, true);
//有时候需要立即执行,然后等到停止触发N秒后,才可以重新触发
/*
fn: 回调函数
wait:多少秒后执行
immediate:立即执行(true/false)
*/
function debounce(fn, wait, immediate) {
//加载执行
let timeOut;
return function () {
const context = this;
const args = arguments;
if (timeOut) clearTimeout(timeOut);
if (immediate) {
const callNow = !timeOut;
timeOut = setTimeout(function () {
console.log("我执行完了")
timeOut=null;
}, wait)
if (callNow) fn.apply(context, args);
} else {
timeOut = setTimeout(function () {
fn.apply(context, args);
}, wait)
}
}
。返回值版实现
。func函数可能会有返回值,所以需要返回函数结果,但是 immediate 为false 的时候,因为使用setTimeout,我们将func.apply(context,args)
值赋值给变量,最后再retrue的时候,值将会一直是undefined,所以只在immediate为true的时候直接返回函数的执行结构
function debounce(fn, wait, immediate) { let timeOut, result; return function () { let context = this; let args = arguments; if (timeOut) clearTimeout(timeOut); if (immediate) { let callNow = !timeOut; timeOut = setTimeout(() => { timeOut = null; }, wait); if (callNow) result= fn.apply(context, args); } else { timeOut = setTimeout(() => { result= fn.apply(context, args); }, wait); } console.log(result); }
2.节流
。原理:规定单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。
。使用场景
拖拽场景,固定时间内只执行一次,防止超高频次触发位置变动。
缩放场景,监控浏览器resize。
。使用时间戳实现
。使用时间戳,当触发事件的时候,我们取出当前的时间戳,然后减去之前的时间戳(最一开的初始值为0),如果
大于设置时间周期,就执行函数,然后更新时间戳为当前的时间戳,如果小于,就不执行。
function throttle(fn, wait) { let context, args; let prvious = 0; return function () { let now = +new Date(); let context = this; let args = arguments; if (now - prvious > wait) { fn.apply(context, args); prvious = now; } } }
。使用定时器实现
。当触发事件的时候,我们设置一个定时器,再触发事件的时候,如果定时器存在,就不执行,
直到定时器执行,然后执行函数,清空定时器,这样可以设置下个定时器。
function throttle(fn, awit) { let timeOut; return function () { const context = this; const args = arguments; if (!timeOut) { timeOut = setTimeout(() => { timeOut = null; fn.apply(context, args); }, awit) } } }

浙公网安备 33010602011771号