【面试题】防抖和节流
1. 防抖和节流
概念
防抖:在一定的时间间隔内,将多次的触发变成一次触发,类似游戏中的回城,你一直触发回城事件,但是最终只能执行一次,等到回城时间一到就回家了
节流:减少在一段时间内的频率,类似游戏中的技能CD,在指定的时间内只能使用一次技能
1. 防抖
1.1 普通防抖
/*
防抖函数
参数一:需要防抖的函数
参数二:延时时间
*/
function debounce (fun,delay){
let timeout = null
return function(){
// 如果有值则清除定时器
if(timeout)
{
clearTimeout(timeout)
}
// 如果没有值则开一个定时器
timeout = setTimeout(() => {
/*
1. 这里使用箭头函数将this的指向外部
2. 补充知识点arguments(实参列表) ,每个实参
列表对应自己内部函数,只有在函数的内部才会产生
实参列表,在这里使用箭头函数,将箭头函数内部的指向arguments,
指向外部
*/
fun.apply(this,arguments)
}, delay);
}
}
function request(e){
console.log('发送请求');
console.log(this);
/*
e是什么时候传进来的?
当window调用该函数的时候将实参传进来
*/
console.log(e);
}
let btn = document.querySelector('button')
btn.addEventListener('click',debounce(request,500))
1.2 防抖升级
/*
防抖函数
参数一:需要防抖的函数
参数二:延时时间
*/
function debounce (fun,delay){
let timeout = null
return function(){
// 如果有值则清除定时器
// 需要注意:清除定时器,不代表把值给清除了
if(timeout)
{
clearTimeout(timeout)
}else{
// 第一次立即执行,后面触发效果和普通防抖一样
fun.apply(this,arguments)
}
// 如果没有值则开一个定时器
timeout = setTimeout(() => {
/*
1. 这里使用箭头函数将this的指向外部
2. 补充知识点arguments(实参列表) ,每个实参
列表对应自己内部函数,只有在函数的内部才会产生
实参列表,在这里使用箭头函数,将箭头函数内部的指向arguments,
指向外部
*/
fun.apply(this,arguments)
}, delay);
}
}
function request(e){
console.log('发送请求');
console.log(this);
/*
e是什么时候传进来的?
当window调用该函数的时候将实参传进来
*/
console.log(e);
}
let btn = document.querySelector('button')
btn.addEventListener('click',debounce(request,1000))
1.3 新增防抖参数(立即执行)
/*
防抖函数
参数一:需要防抖的函数
参数二:延时时间
参数三:是否开启立即执行
注意:这里的立即执行指的是第一次点击时
不进行延时,而这里的第一次指的是每次延时后
再次点击都算第一次
*/
function debounce (fun,delay,immediate=false){
let timeout = null
return function(){
// 如果有值则清除定时器
// 需要注意:清除定时器,不代表把值给清除了
if(timeout)
{
clearTimeout(timeout)
}
// 判断是否开启立即执行
if(immediate)
{
// 第一次进来timeout值为null,取反为真
let first = !timeout
if(first)
{
fun.apply(this,arguments)
}
timeout = setTimeout(() => {
// 延时过后恢复timeout的值,让它能够调用函数
timeout = null
}, delay);
}else
{
// 如果没有值则开一个定时器
timeout = setTimeout(() => {
/*
1. 这里使用箭头函数将this的指向外部
2. 补充知识点arguments(实参列表) ,每个实参
列表对应自己内部函数,只有在函数的内部才会产生
实参列表,在这里使用箭头函数,将箭头函数内部的指向arguments,
指向外部
*/
fun.apply(this,arguments)
}, delay);
}
}
}
function request(e){
console.log('发送请求');
console.log(this);
/*
e是什么时候传进来的?
当window调用该函数的时候将实参传进来
*/
console.log(e);
}
let btn = document.querySelector('button')
btn.addEventListener('click',debounce(request,1000,true))
2. 节流
2.1 第一种写法
function throttle (fun,delay){
let previous = 0
return function(){
let current = new Date()
// 大于延时的时间,就表示技能CD已经好了可以用了
console.log(current - previous);
if(current - previous > delay)
{
fun.apply(this,arguments)
// 更新时间
previous = current
}
}
}
function request(e){
console.log('发送请求');
console.log(this);
/*
e是什么时候传进来的?
当window调用该函数的时候将实参传进来
*/
console.log(e);
}
let btn = document.querySelector('button')
btn.addEventListener('click',throttle(request,1000))
2.2 第二种写法
function throttle (fun,delay){
let flag = true
return function(){
if(flag)
{
fun.apply(this,arguments)
flag = false
setTimeout(() => {
// 延时时间一到恢复技能使用权
flag = true
}, delay);
}
}
}
function request(e){
console.log('发送请求');
console.log(this);
/*
e是什么时候传进来的?
当window调用该函数的时候将实参传进来
*/
console.log(e);
}
let btn = document.querySelector('button')
btn.addEventListener('click',throttle(request,2000))
总结
以上就是今天要讲的内容,希望对大家有所帮助!!!