防抖节流函数:
防抖:
当持续触发事件时, 一定时间内没有再触发,事件处理函数执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时
假如期限值是200ms
1、在200ms 内没有再次触发事件,那么就执行函数;
2、如果在200ms 内再次触发了滚动事件,那么当前计时器取消,重新开始计时;
function debounce(fn,delay){
let timer = null;
return function(){
if(timer){
//进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
clearTimeout(timer)
}
timer = setTimeout(fn,delay)
}
}
//防抖debounce代码:
function debounce(fn,delay) {
var timeout = null; // 创建一个标记用来存放定时器的返回值
return function (e) {
// 每当用户输入的时候把前一个 setTimeout clear 掉
if(timeout){
clearTimeout(timeout);
}
// 然后又创建一个新的 setTimeout, 这样就能保证interval 间隔内如果时间持续触发,就不会执行 fn 函数
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
};
}
// 处理函数
function handle() {
console.log('防抖:', Math.random());
}
//滚动事件
window.addEventListener('scroll', debounce(handle,500));
节流函数:
当持续触发事件时,保证一定时间段内只调用一次事件处理函数。
函数防抖(debounce):
触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
函数节流(throttle):高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。
实现函数节流我们主要有两种方法:时间戳和定时器
// 节流 (时间戳)
var throttle = function(fn,delay){
var pre = Date.now();
return function(){
var _this = this;
var args = arguments;
var now = Date.now();
if(now-pre>=delay){
fn.apply(_this,args);
pre = Date.now()
}
}
}
function handle() {
console.log(Math.random());
}
window.addEventListener('scroll', throttle(handle, 1000));
当触发事件的时候,我们设置一个定时器,再次触发事件的时候,如果定时器存在,就不执行,直到delay时间后,定时器执行执行函数,并且清空定时器,这样就可以设置下个定时器。
// 定时器
var throttle = function (fn,delay){
var timer = null;
return function (){
var _this = this;
var args= arguments;
if(!timer){
timer = setTimeout(()=>{
fn.apply(_this,args)
timer = null
},delay)
}
}
}
当remaining<=0时表示该执行事件处理函数了(保证了第一次触发事件就能立即执行事件处理函数和每隔delay时间执行一次事件处理函数)。
如果还没到时间的话就设定在remaining时间后再触发 (保证了最后一次触发事件后还能再执行一次事件处理函数)。
当然在remaining这段时间中如果又一次触发事件,那么会取消当前的计时器,并重新计算一个remaining来判断当前状态。
// 节流throttle代码(时间戳+定时器):
var throttle = function (fn,delay){
var timer = null;
var startTime = Date.now(); // 进来开始的时间
return function(){
var currentTime = Date.now();
var remaining = delay-(currentTime-startTime);
var _this = this;
var args = arguments;
clearTimeout(timer);
if(remaining<=0){
fn.apply(_this.args)
startTime = Date.now()
}else{
timer = setTimeout(fn,remaining)
}
}
}