防抖的定义
多次触发事件后,事件处理函数只执行一次,并且是在触发操作结束时执行。
防抖的意义
实际工作中,我们经常性的会通过监听某些事件完成对应的需求,如滚动监听、按键监听和窗口大小变动监听。会在短时间内触发多次绑定事件, 我们知道DOM操作是很耗费性能的,如果在监听中,做了一些DOM操作,那无疑会给浏览器造成大量性能损失。
防抖的原理
对处理函数进行延时操作,若设定的延时到来之前,再次触发事件,则清除上一次的延时操作定时器,重新定时。
代码演示
let timer;
window.onscroll = function () {
if(timer){
clearTimeout(timer)
}
timer = setTimeout(function () {
//滚动条位置
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
timer = undefined;
},200)
}
防抖函数封装
/**
* 防抖函数
* @param method 事件触发的操作
* @param delay 多少毫秒内连续触发事件,不会执行
* @returns {Function}
*/
function debounce(method,delay) {
let timer = null;
return function () {
let self = this,
args = arguments;
timer && clearTimeout(timer);
timer = setTimeout(function () {
method.apply(self,args);
},delay);
}
}
window.onscroll = debounce(function () {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
},200)
理解须知
function是一个指向Function对象,函数名是一个指向函数的指针。那么在函数体内,就会有一个作用域,即this关键字。 表示当前函数的作用域,在闭包中(理解成函数里面定义函数,此时内部定义的函数只是在当前函数内部使用,而内部函数可以调用外部函数定义的变量),而apply方法是函数对象的一个回调方法,用于调用传进来的函数指针所在的函数体,跟call方法都能实现相同的功能,区别在于前者支持传入数组,后者只能严格匹配参数。而 两者第一个参数就是改变函数的作用域,用于扩充函数赖以运行的作用域,更多参考请阅读原文https://www.cnblogs.com/chengzi/p/3990571.html。
防抖适用性
用于解决多次触发事件时的性能问题,但是针对实时性高的业务不适用。如图片懒加载
节流的定义
触发函数事件后,短时间间隔内无法连续调用,只有上一次函数执行后,过了规定的时间间隔,才能进行下一次的函数调用。
节流的意义
针对于频繁触发的业务,实时性要求高的可以尽可能保证在满足业务需求的前提下降低系统负载。
节流的原理
对处理函数进行延时操作,若设定的延时到来之前,再次触发事件,则清除上一次的延时操作定时器,重新定时。
代码演示
let startTime = Date.now(); //开始时间
let time = 500; //间隔时间
let timer;
window.onscroll = function throttle(){
let currentTime = Date.now();
if(currentTime - startTime >= time){
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
startTime = currentTime;
}else{
clearTimeout(timer);
timer = setTimeout(function () {
throttle()
}, 50);
}
}
节流封装
/**
* 节流函数
* @param method 事件触发的操作
* @param mustRunDelay 间隔多少毫秒需要触发一次事件
*/
function throttle(method, mustRunDelay) {
let timer,
args = arguments,
start;
return function loop() {
let self = this;
let now = Date.now();
if(!start){
start = now;
}
if(timer){
clearTimeout(timer);
}
if(now - start >= mustRunDelay){
method.apply(self, args);
start = now;
}else {
timer = setTimeout(function () {
loop.apply(self, args);
}, 50);
}
}
}
window.onscroll = throttle(function () {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
},800)
阅文先关文章请点击前往