1.防抖deboune
防抖第一次不是立即执行,都是延后执行。只要定时器还在,一直调用会一直取消重新创建定时。直到定时正常结束执行方法。(当然也可以使用immediate参数让方法先执行)
等一等,别着急,如果一直有新操作,那就一直推迟执行。
//防抖函数
function debounce(fn,delay) {
let timeId;
return (...args) => {
if (timeId) {
console.log("取消之前正在执行的函数")
clearTimeout(timeId)
}
timeId = setTimeout(() => {
fn.apply(this,args)//执行原来定义的函数+ 参数
clearTimeout(timeId)
},delay)
}
}
function hello(info) {
console.log("hello jason",info)
}
//获取定义的防抖函数
const testFn = debounce(hello,100)
testFn("11");
testFn("22");
testFn("33");
支持先执行immediate参数版本
function debounce(func, delay,immediate) {
let timer =null;
return function() {
const callNow = immediate && !timer; // 是否立即执行,每次判断上一次的timer 是否还存在
if(callNow) {
func.apply(this, arguments)
}
if(timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
if(!immediate) {
func.apply(this, arguments)
}
}, delay);
}
}
const fn1 = debounce((msg) => {console.log(msg)}, 1000,false)
fn1('11')
fn1('22')
fn1('33')
fn1('44')
适用场景:
- 搜索框输入联想(用户停止输入一段时间后再发送请求)
- 窗口大小调整(resize)后重新计算布局
- 表单验证(用户输入完成后再校验,而不是每输入一个字符就校验一次)
2.节流throttle
节流第一次是立即执行,后面的之前会根据上一次的时间戳,是否满足最大的延迟时间才再次执行。
固定时间只执行一次,不管你触发多少次(节流会稀释函数的执行频率)
//节流函数
function throttle(fn,delay) {
let last = 0;
return (...args) => {
let now = Date.now();//now的时间单位是 毫微秒 和 settimeout的delay是一致
console.log("now",now,"last",last)
if(now > last + delay ){
last = now;
fn.apply(this,args)//立刻执行原来定义的函数+ 参数
}
}
}
function hello(info) {
console.log("hello jason",info)
}
const testFn = throttle(hello,300)
testFn("11")
testFn("22")
testFn("33")
setTimeout(() => {
testFn("44")
}, 2000);
适用场景:
- 滚动加载更多内容(scroll)
- 鼠标移动事件(mousemove),比如拖拽
- 游戏中的按键频率限制
- 高频点击提交按钮防止重复提交