//没有考虑上下文和错误处理版本的防抖函数就如下而
/**
*
* @param {function} func 执行的函数
* @param {number} time 防抖的时间
*/
const debounce = (func,time = 500) =>{
let timeout;
return () => {
if (timeout) clearTimeout(timeout);
setTimeout(func,time);
}
}
const eventdo = debounce(some,1000);
element.onscroll = eventdo;
上面有个问题就是如果再场景2那种情况,用户提交数据请求是发不出去的。而且不停点击,请求就一直不发,这显然是不科学的,我们就要改进这个函数了。
/**
*
* @param {function} func 执行的函数
* @param {boll} immediate 是否马上执行一遍
* @param {number} time 防抖的时间
*/
//简易版本防抖函数的实现
const debounce = (func, immediate = false, time = 500) => {
let timeout,
hasImmediate = immediate;
let later = (args) => {
timeout = null; //这里设为null是再马上需要调用一次那种情况用的。就是说如果执行了,就表示重新再来
if (args) func(...args);
}
return (...args) => {
if (timeout)
clearTimeout(timeout);
if (immediate) {
const callNow = !timeout; //马上执行一遍
if (callNow)
func(...args);
setTimeout(later,time);//防止疯狂点击,因为我们没有传参数给later,所以later函数的args是undefined,它里面也不会执行的
} else {
setTimeout(() =>later(args),time);
}
}
}
我们可见如果传入了immediate参数,这个防抖函数会马上执行一遍,在之后的time时间内,都不能点击,如果疯狂点击这个时间也不断延长。这样就实现了一个基本的防抖函数了。
/**
*
* @param {function} func 执行的函数
* @param {number} wait 节流时间
*/
//简易版本节流函数的实现
const throttle = (func,wait) =>{
let previous = 0;//记录函数上一次执行的时间
return (...arg) =>{
let now = Date.now();
if (!previous) previous = now;
let remaining = wait - (now - previous);//剩余时间
if (remaining < 0 || remaining > wait){
//超过了节流时间
//执行函数
func(...arg);
previous = now;
}
}
}
函数节流和函数防抖都是利用了setTimeout的特性进行操作的,在优化函数频繁调用中十分有用。