防抖(短时间内多次重复操作,只执行最后一次操作)
应用场景举例
- 改变页面大小的统计
- 滚动页面位置的统计
- 输入框连续输入次数的控制
- 防止表单多次提交
- …
解决思路:
- 设置定时器 timer
- timer 时间到了之后执行方法
- 如果时间没到,又执行了操作,就把clearTimeout清除timer(上次操作就相当于取消了)然后到 2
/**
* 防抖函数封装
*
* @param fun 要执行的函数
* @param delay 延时,默认500毫秒
* @returns
*/
function debounce(fun, delay = 500) {
let timer;
return function () {
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(() => {
fun.apply(context,args);
}, delay);
}
}
// 支付方法
function pay() {
console.log('pay');
}
// 此处获取一个页面上的按钮做测试
const dom = document.getElementById('dom');
dom.addEventListener('click', debounce(pay));
总结:
第一次点击按钮
1:定义一个空的timer,let timer(方便区分叫做timer1)
2:返回闭包函数并且执行该函数
清空定时器timer1,此时timer1只申明,什么都不发生
设置一个1s的延时,之后执行pay方法,
并且timer1 等于 这个定时器
此时若无任何操作,则会在定时结束后执行pay方法
第二次点击(第一次timer时间还未到)
1:定义一个空的timer(方便区分叫做timer2)
2:返回闭包函数并且执行该函数
此时这个闭包保存了上一次操作设置的timer1
清空定时器clearTimeout(timer1);所以上次操作会被取消
设置一个新的timer,1s的延时,之后执行pay方法
并且timer2 = 这个定时器
同理在延时时间内再次触发就会取消前一次的操作,达到防抖的目的
节流(规定直接内只执行一次操作)
使用场景
- 监听页面滚动,触发对应方法
解决思路
- 设置定时器 timer
- timer 时间到了之后执行方法(timer = null)
- 判断新的操作来的时候,是否隔了指定时间 if(timer)
如果 timer 存在,就代表上次操作正在进行,
因为进行完了会timer = null,第一次操作时候 timer也未赋值
那我们就直接return,忽略此次操作
反之则到2
/**
* 节流函数封装(使用timer)
*
* @param fun 要执行的函数
* @param delay 延时,默认500毫秒
* @returns
*/
function throttle1(fun, delay = 500) {
let timer;
return function () {
let context = this;
let args = arguments;
if (timer) { return }
timer = setTimeout(() => {
fun.apply(context, args);
timer = null;
}, delay)
}
}
/**
* 节流函数封装(使用Data)
*
* @param fun 要执行的函数
* @param delay 延时,默认500毫秒
* @returns
*/
function throttle2(fun, delay = 1000) {
let pre = 0;
return function () {
let context = this;
let args = arguments;
let now = new Date();
// (now-pre) 当前触发距离上一次触发过了多少毫秒
if (now - pre > delay) {
fun.apply(context, args);
pre = now;
}
}
}
// 改变背景颜色方法
function coloring() {
let r = Math.floor(Math.random() * 255);
let g = Math.floor(Math.random() * 255);
let b = Math.floor(Math.random() * 255);
document.body.style.background = `rgb(${r},${g},${b})`
}
window.addEventListener('resize', throttle1(coloring));
扩展js知识
在调用函数时候,浏览器每次都会传递两个隐含的参数
1.函数上下文 this
2.封装实参的对象 arguments
每个Date对象都保存了一个从1970年1月1号起经过的毫秒数,所有Date对象可以相减,得到两个时间相差多少毫秒