
我们都遇到过这样的场景,在某个搜索框中输入自己想要搜索的内容:
这就是防抖的操作:只有在某个时间内,没有再次触发某个函数时,才真正的调用这个函数;
游戏理解: 防抖就回城
生活理解: 坐电梯

<!-- //第三方库使用防抖节流 -->
<input type="text">
<script src="https://cdn.jsdelivr.net/npm/underscore@1.13.1/underscore-umd-min.js"></script>
<script>
const inputEl = document.querySelector('input')
let count = 0
const inputChange = function (event) {
count++
console.log(`发送了我们的第${count}次网络请求`, this,event);
}
// 防抖只执行一次
inputEl.oninput=_.debounce(inputChange,2000)
<!-- //第三方库使用防抖节流 -->
<input type="text">
<!-- <script src="https://cdn.jsdelivr.net/npm/underscore@1.13.1/underscore-umd-min.js"></script> -->
<script>
const inputEl = document.querySelector('input')
let count = 0
const inputChange = function () {
count++
console.log(`发送了我们的第${count}次网络请求`);
}
// 防抖只执行一次
inputEl.oninput = debounce(inputChange, 2000)
// 1 防抖的过程需要传递两个值一个是函数fn另一个是时间
function debounce(fn, times) {
// 定义一个定时器来来记录上一次的定时器函数的状态
let timer = null
// 2 在接受这两个值时需要返回一个函数
const _debounce = function () {
// 3 在处理防抖时 需要只执行一次 这里需要一个计时器
// 4 计时器有一个返回的id属性值 ,利用返回的id,让函数只执行最后一次
// 5 如果有这个id 则停止计时器
if (timer) clearInterval(timer) //取消上一次定时器
timer = setTimeout(() => { //延迟执行
fn() //外部传入的函数
}, times)
}
return _debounce
}
</script>
优化
// 防抖的关键在于定时器的开始与清零
function debounce(callback,delaytime){
// 定义计时器
let timer=null
return function(){
//如果定时器不是null 则需要重新计时
if (timer!=null) {
clearTimeout(timer)
}
//如果定时器还是空 ,则开始倒计时
timer=setTimeout(()=>{
callback&&callback()
}, delaytime)
}
}
注意上面的this指向为window 参数传递为undefined
<input type="text">
<!-- <script src="https://cdn.jsdelivr.net/npm/underscore@1.13.1/underscore-umd-min.js"></script> -->
<script>
const inputEl = document.querySelector('input')
let count = 0
const inputChange = function (event) {
count++
console.log(`发送了我们的第${count}次网络请求`, this,event); //这里的this指向window ,event传递的参数指向undefined
//因此需要重新绑定this
}
// 防抖只执行一次
inputEl.oninput = debounce(inputChange, 2000)
// 1 防抖的过程需要传递两个值一个是函数fn另一个是时间
function debounce(fn, times) {
// 定义一个定时器来来记录上一次的定时器函数的状态
let timer = null
// 2 在接受这两个值时需要返回一个函数 (真正需要执行的函数)
const _debounce = function (...args) { //这里处理args传递的参数
// 3 在处理防抖时 需要只执行一次 这里需要一个计时器
// 4 计时器有一个返回的id属性值 ,利用返回的id,让函数只执行最后一次
// 5 如果有这个id 则取消上一次计时器
if (timer) clearInterval(timer) //取消上一次定时器
timer = setTimeout(() => { //延迟执行
fn.apply(this,args) //外部传入的函数
//在这里重新绑定this(不绑定this指向的是windows =>这里改变this重新指向调用者input)
}, times)
}
return _debounce
// 问题: 主函数需要先执行 ,只不过返回的是undefined
//undefined 游览器自己处理不做判断
}
</script>
<!-- 题注 当用户输入一次时, 先执行一次 =>产生联想 -->
<!-- //第三方库使用防抖节流 -->
<input type="text">
<script>
const inputEl = document.querySelector('input')
let count = 0
const inputChange = function (event) {
count++
console.log(`发送了我们的第${count}次网络请求`, this, event); //这里的this指向window ,event传递的参数指向undefined
//因此需要重新绑定this
}
// 防抖只执行一次
inputEl.oninput = debounce(inputChange, 2000,true) //这里可以传入第三个参数
// 1 防抖的过程需要传递两个值一个是函数fn另一个是时间
function debounce(fn, times, imediate=false) { //immediate是否立即执行,默认情况下是不需要立即执行的传入false
let timer = null
// 定义全局判断上一次是否是立即执行
let isVoke=false
const _debounce = function (...args) {
if (timer) clearInterval(timer) //取消上一次定时器
//判断是否需要立即执行
if (imediate &&!isVoke) { //!isVoke=true
fn.apply(this,args)
// imediate=false //立即执行完成之后改成false 分析问题 当下一次重新输入时 不会立即执行=>延迟执行
isVoke=true //这里赋值为true 当上一次执行完毕后赋值为true //让其延迟执行
}else{
//延迟执行
timer = setTimeout(() => { //延迟执行
fn.apply(this, args) //外部传入的函数
isVoke=false //abcd=> 当abcd执行完后重启false 在判断是否立即执行
}, times)
}
}
return _debounce
}