一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情
前言
函数的 防抖和节流 是经典的面试题了,面试官为什么喜欢考这个呢,是因为不论在工作还是项目中都可以起到 性能优化 的作用,这也是比较常见而且简单的优化手段了。
防抖
概念: 在事件触发一段时间里只执行最后一次。
这里提到了 只执行最后一次 ,那我们怎么让它只执行最后一次? 实现了这样的效果,就是真正的防抖函数了。
我们来模拟一下输入时发送请求的场景:
<input type="" name="" class="inp">
js 代码:
const inp = document.querySelector('.inp');
function oninput (e) {
// 发送请求
console.log(e.target.value);
}
inp.addEventListener('input', oninput)
上述代码中,只要输入一个字符,就会发送一次请求,会造成大量的资源浪费,虽然服务器顶得住,但难免是不好的,我认为前端的工作就是 用最少的代码,实现最优的效果。
那既然输入一个字符就发一次,那么我们能不能延迟 1s 再发呢,这个时候 就需要定时器 setTimeout 了。
const inp = document.querySelector('.inp');
function oninput (e) {
setTimeout(() => {
// 发送请求
console.log(e.target.value);
}, 1000)
}
inp.addEventListener('input', oninput);
看来是不行~~
因为当我们触发 input 事件时,都会新增一个定时器,虽然实现延迟的效果,但没有实现我们说的 只执行最后一次,这样的效果。
那我们稍微优化一下代码。
const inp = document.querySelector('.inp');
let timer;
function oninput (e) {
clearTimeout(timer);
timer = setTimeout(() => {
// 发送请求
console.log(e.target.value);
}, 1000)
}
inp.addEventListener('input', oninput);
好像是成功啦 😄 哈哈哈~~
我们输入6个字符,结果只出现了一次。我们把代码封装一下。
// debounce.js
let inp = document.querySelector('.inp');
function oninput (e) {
console.log(e.target.value);
}
function debounce (fn, delay) {
let timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay)
}
}
inp.addEventListener('input', debounce(oninput, 1000))
debounce 中传入两个参数[ 触发的事件函数,延迟的时间 ],大功告成了~~
节流
概念: 在执行事件时一段时间内只触发一次。
那我们怎么控制它在 一段时间内只触发一次 呢?我们可以理解为 降低频率,何为降低频率?就是一段时间内,如果触发多次事件(函数),但是我们只会保留一次,其他的不保留。实现它,就实现了 节流 的效果。
一段时间内只触发一次,我们可以想象成一个 阀门 ,一段时间开一次然后又关闭,一段时间开一次然后又关闭,如此的反复循环下去...
我们模拟一下点击按钮时的 如何 降低频率
<button class="btn">发送</button>
js 代码:
let btn = document.querySelector('.btn');
let flag = true;
function handlerClick (e) {
if (flag) {
flag = false;
console.log(e.target.textContent);
}
}
btn.addEventListener('click', handlerClick);
这时,控制台只会打印一次,因为我们把阀门打开之后立马又关闭了,没有达到反复循环的效果,那我们应该怎么做呢? 我们可以加上一个定时器 setTimeout 帮助我们过一段时间后打开阀门。
假设是 1s 钟,我们修改一下代码:
let btn = document.querySelector('.btn');
let flag = true;
function handlerClick (e) {
if (flag) {
flag = false;
console.log(e.target.textContent);
setTimeout(() => {
flag = true;
}, 1000)
}
}
btn.addEventListener('click', handlerClick);
是不是有那感觉了,哈哈哈,太对了哥,哥太对~~
我们把代码封装一下吧。
// throttle.js
let btn = document.querySelector('.btn');
function handlerClick (e) {
console.log(e.target.textContent);
}
function throttle (fn, delay) {
let flag = true;
return function () {
if (flag) {
flag = false;
fn.apply(this, arguments);
setTimeout(() => {
flag = true;
}, 1000)
}
}
}
btn.addEventListener('click', throttle(handlerClick, 1000));
throttle 中传入两个参数[ 触发的事件函数,延迟的时间 ],大功告成了~~
总结
以上就是本次分享的全部内容~~
如果觉得文章写得不错,对你有所启发的,请不要吝啬 点个 赞 和 关注 并在 评论区 留下你宝贵的意见哦~~😃