防抖函数的作用
防抖函数的作用就是控制函数在一定时间内的执行次数。防抖意味着N秒内函数只会被执行一次,如果N秒内再次被触发,则重新计算延迟时间。
举例说明: 小思最近在减肥,但是她非常吃吃零食。为此,与其男朋友约定好,如果10天不吃零食,就可以购买一个包(不要问为什么是包,因为包治百病)。但是如果中间吃了一次零食,那么就要重新计算时间,直到小思坚持10天没有吃零食,才能购买一个包。所以,管不住嘴的小思,没有机会买包(悲伤的故事)… 这就是 防抖。
防抖函数实现
事件第一次触发时,timer 是 null,调用 later(),若 immediate 为true,那么立即调用 func.apply(this, params);如果 immediate 为 false,那么过 wait 之后,调用 func.apply(this, params)事件第二次触发时,如果 timer 已经重置为 null(即 setTimeout 的倒计时结束),那么流程与第一次触发时一样,若 timer 不为 null(即 setTimeout 的倒计时未结束),那么清空定时器,重新开始计时。 function debounce(func, wait, immediate = true) { let timeout, result; // 延迟执行函数 const later = (context, args) => setTimeout(() => { timeout = null;// 倒计时结束 if (!immediate) { //执行回调 result = func.apply(context, args); context = args = null; } }, wait); let debounced = function (...params) { if (!timeout) { timeout = later(this, params); if (immediate) { //立即执行 result = func.apply(this, params); } } else { clearTimeout(timeout); //函数在每个等待时延的结束被调用 timeout = later(this, params); } return result; } //提供在外部清空定时器的方法 debounced.cancel = function () { clearTimeout(timer); timer = null; }; return debounced; };immediate 为 true 时,表示函数在每个等待时延的开始被调用。immediate 为 false 时,表示函数在每个等待时延的结束被调用。
防抖的应用场景
搜索框输入查询,如果用户一直在输入中,没有必要不停地调用去请求服务端接口,等用户停止输入的时候,再调用,设置一个合适的时间间隔,有效减轻服务端压力。表单验证按钮提交事件。浏览器窗口缩放,resize事件(如窗口停止改变大小之后重新计算布局)等。节流函数的作用
节流函数的作用是规定一个单位时间,在这个单位时间内最多只能触发一次函数执行,如果这个单位时间内多次触发函数,只能有一次生效。
节流函数实现
function throttle(func, wait, options = {}) { var timeout, context, args, result; var previous = 0; var later = function () { previous = options.leading === false ? 0 : (Date.now() || new Date().getTime()); timeout = null; result = func.apply(context, args); if (!timeout) context = args = null; }; var throttled = function () { var now = Date.now() || new Date().getTime(); if (!previous && options.leading === false) previous = now; //remaining 为距离下次执行 func 的时间 //remaining > wait,表示客户端系统时间被调整过 var remaining = wait - (now - previous); context = this; args = arguments; //remaining 小于等于0,表示事件触发的间隔时间大于设置的 wait if (remaining <= 0 || remaining > wait) { if (timeout) { //清空定时器 clearTimeout(timeout); timeout = null; } //重置 previous previous = now; //执行函数 result = func.apply(context, args); if (!timeout) context = args = null; } else if (!timeout && options.trailing !== false) { timeout = setTimeout(later, remaining); } return result; }; throttled.cancel = function () { clearTimeout(timeout); previous = 0; timeout = context = args = null; }; return throttled; }禁用第一次首先执行,传递 {leading: false} ;想禁用最后一次执行,传递 {trailing: false}
节流的应用场景
按钮点击事件拖拽事件onScoll计算鼠标移动的距离(mousemove)