防抖函数的定义
通过延迟执行的方式,降低某种执行特别频繁事件造成的浏览器性能问题或者是过多请求服务器行为;
一个需要频繁触发的函数需要在规定时间内,只让最后一次生效,前面的不生效
使用场景
防抖函数一般用在onScroll,onResize,onmousemove等操作很频繁的事件
第一种:
// 当用户输入文字后请求后端接口返回数据
/*
* 基础代码
*/
// 获取dom元素
var inputEle = document.getElementById('inputEle');
// 定义一个全局变量用来存储要延迟执行的方法
var t = null;
// 给dom元素绑定键盘抬起事件
inputEle.addEventListener("keyup", function(e){
// 清除快速输入时的延迟执行行为
t && clearTimeout(t);
// 从新定义延迟执行请求
t = setTimeout(function(){
//ajax(...); 发送请求到服务器
}, 300);
});
// 上边的代码用到了全局变量,污染全局
/*
* 改进后的代码
*/
(function(){
// 后去dom元素
var inputEle = document.getElementById('inputEle');
// 给dom元素绑定键盘抬起事件
inputEle.addEventListener('keyup', function(e){
var t = null;
return function(){
t && clearTimeout(t);
t = setTimeout(function(){
// ajax(...); 发送请求到服务器
}, 300);
}
}(e))
})
第二种:封装一个防抖函数
/*
* 封装防抖函数
* t:延迟多久才执行
* f: 需要延迟执行的函数方法
*/
function debounce(t, f){
// 定义一个变量用来存储定时器
var timer;
// 把方法返回出去,这样就解决了使用全局变量,形成闭包
return function(){
// 记录当前调用函数时的this
var that = this;
// 保存调用该函数的时候传递的参数
var args = arguments;
// 判断如果定时间已经有,先清除
timer && clearTimeout(timer);
// 然后从新赋值延迟定时器
timer = setTimeout(function(){
//使用apply方法解决this执行问题,把this指向到调用此方法的this上,
// 然后通过args把参数以数组的形式传过去
f.apply(that, args);
}, t);
}
}
/*
* 封装防抖函数
* t:延迟多久才执行
* f: 需要延迟执行的函数方法
* 通过使用箭头函数减少两步操作
*/
function debounce_1(t, f){
// 定义一个变量用来存储定时器
var timer;
// 把方法返回出去,这样就解决了使用全局变量,形成闭包
return function(){
// 判断如果定时间已经有,先清除
timer && clearTimeout(timer);
// 然后从新赋值延迟定时器
// 这里的定时器使用了箭头函数,所以this执行到了调用该方法的this,arguments也是调用改法发的arguments
timer = setTimeout(()=>{
//使用apply方法解决this执行问题,把this指向到调用此方法的this上,
// 然后通过arguments把参数以数组的形式传过去
f.apply(that, arguments);
}, t);
}
}
var i = 0;
box.addEventListener('mousemove', debounce(2000, function(){
this.innerHTML = i++;
}));
throttle 节流
throttle(节流),当某个函数频繁执行的时候,让他在规定的时间内才执行一次,降低执行的频繁率。
第一种:通过一个标识符来判断
/*
* t 表示多长时间执行一次方法
* f 表示要执行的方法
*/
function throttle(t, f){
// 定义一个标识,用来表示当前方法时候正在延迟执行
let mark;
return function(){
// 记录当前执行方法的this指向
// 记录当前执行方法的参数
var that = this;
var args = arguments;
if(!mark){
mark = true;
setTimeout(function(){
f.apply(that, args);
mark = null;
}, t);
}
}
}
var i = 0;
box.addEventListener('mousemove', throttle(2000, function(){
this.innerHTML = i++;
}));
第二种:通过时间戳比较方式
/*
* t 表示多长时间执行一次方法
* f 表示要执行的方法
*/
function throttle(t, f){
// 记录一开始执行的
var before = new Date();
// 返回
return function(){
var that = this,
args = arguments,
now = new Date();
if(now - before - t > 0){
setTimeout(function(){
f.apply(that, arguments) ;
before = now;
}, t);
}
}
}
/*
* 通过使用箭头函数,可以不用记录this和arguments
*/
function throttle(t, f){
// 首先记录一下第一次调用该方法的时间
let before = new Date();
// 通过闭包返回该方法
return function(){
// 记录当前执行的时间
var now = new Date();
// 如果要是时间小于0的时候不执行,如果时间大于0的话就执行方法
if(now - before - t > 0){
// 通过延迟方法执行箭头函数来实现
setTimeout(()=>{
// 当前的 this指向的是调用该函数的this,参数是传入过来的参数
f.apply(this, arguments);
before = now;
}, t)
}
}
}
var i = 0;
box.addEventListener('mousemove', throttle(2000, function(){
this.innerHTML = i++;
}));
使用场景
节流函数一般用在提交表单,点赞,收藏等和后台进行异步交互的时候
总结:
防抖函数和节流函数都是用来提高性能的,并且都是通过延迟执行,然后通过判断是否执行该方法来实现的。