1、防抖定义
防抖与节流其实算不上js的啥特定功能,只是开发过程当中经常有这样的需求才做独立的归类。比如对于短时间内连续触发的事件,如滚动事件,如下代码:
<head>
<meta charset="UTF-8">
<title>document</title>
<style>
h2{
height: 600px;
}
</style>
</head>
<body id="body">
<h2>h2</h2>
<h2>h2</h2>
<h2>h2</h2>
<script>
window.onscroll = function onscroll(){
var scrollTop = document.documentElement.scrollTop;
// 短时间内会触发很多的事件处理
console.log(scrollTop);
}
</script>
</body>
防抖的含义就是让某个时间内只处理一次即可,如下代码:
<head>
<meta charset="UTF-8">
<title>document</title>
<style>
h2 {
height: 600px;
}
</style>
</head>
<body id="body">
<h2>h2</h2>
<h2>h2</h2>
<h2>h2</h2>
<script>
function scrollHandle() {
var scrollTop = document.documentElement.scrollTop;
console.log(scrollTop);
};
function debounce(fn,delay){
// 这里是利用了闭包私有变量的缓存功能,这样n个滚动事件用的都是同一个timer
var timer = null;
return function(){
if(timer){
// 如果是在滚动的过程中那么timer会一直被新的滚动事件所取消,即一直不打印
clearTimeout(timer);
}
// 直到停止滚动后,因为是最后一个滚动事件了,这里的timer设置执行后,
// 此时将不会再有新的事件去取消timer了,程序也将按设置的delay去执行一次fn函数体
timer = setTimeout(fn,delay);
}
};
window.onscroll = debounce(scrollHandle,80);
</script>
</body>
上述代码不一定要用闭包去处理,用全局的timer也可以,代码更简洁,不好之处就是timer是全局变量易污染,如下代码:
<script>
var timer = null;
window.onscroll = scrollHandle;
function scrollHandle() {
if(timer){
clearTimeout(timer);
}
timer = setTimeout(function(){
var scrollTop = document.documentElement.scrollTop;
console.log(scrollTop);
},80);
};
</script>
2、节流定义
上面实现了防抖的功能,在松开鼠标之后或者是滚轮停止之后才触发事件处理,但如果我想在松开鼠标之前或者是滚轮停止之前的某个时间段内也做节流型打印是否可以呢,答案是可以的,如以下代码:
<head>
<meta charset="UTF-8">
<title>document</title>
<style>
h2 {
height: 600px;
}
</style>
</head>
<body id="body">
<h2>h2</h2>
<h2>h2</h2>
<h2>h2</h2>
<script>
function scrollHandle() {
var scrollTop = document.documentElement.scrollTop;
console.log(scrollTop);
};
function throttle(fn,delay){
var working = false;
return function(){
// 判断如果有事件在处理中的话直接返回,不接受新的事件处理
if(working){
return;
}
// 当接受了一个事件处理时要将working设置为true
working = true;
setTimeout(function(){
fn();
// 在delay毫秒处理完事件之后要把working变为false,重新接受新的事件处理
working = false;
},delay);
}
};
window.onscroll = throttle(scrollHandle,200);
</script>
</body>