防抖函数的作用是什么?请实现一个防抖函数
防抖函数的作用
防抖函数的作用就是控制函数在一定时间内的执行次数。防抖意味着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)
防抖与节流区别
防抖: 触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间;
思路: 每次触发事件时都取消之前的延时调用方法:
节流: 高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率。
思路:每次触发事件时都判断当前是否有等待执行的延时函数。