写在前面
防抖:debounce
, 节流 : throttle
;这俩个名词大家都不陌生,不管是学习,面试,笔试,偶尔总要提提,网上的参考文献也是大有篇章,其中有好多优秀的文章都写的很好了,大家都可以参考的来理解,我们的目的只有一个,那就是理解,并学习,从而创新。我的目的就是从保姆的角度来解释一下这俩个技术,以便大家容易理解;
应用场景
这俩个技术主要是用于web实践中对于事件执行时间的把控,如windows的input,mouse相关事件,keyup等,对于这俩个名词分别解释为:防抖(debounce):一段时间后执行一次
;节流(throttle):一段时间内执行一次
;这样还好理解一点吧,下面我们通过一段实例来解析下俩个东西,重点以防抖为对象,节流只是控制开关有别;
实战解析
先看一段防抖代码,这是我光明正大从其他博主那复制来的
function debounce(fn, delay = 300) {
// delay 秒后执行一次
let timer = null; //定时器开关,利用闭包保存变量
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
//this:让函数获得调用者的指向
//arguments:函数的参数,由于此处无法断言
//故用argument
fn.apply(this, arguments);
}, delay)
}
}
上面我尽可能的加了每句的注释,在直接看懂这个函数之前,你需要了解 闭包 ,定时器,apply函数
这里我做个简单的解释:
- 闭包的作用:通过一系方法,将函数内部的变量(局部变量)转化为全局变量。我们这里return 的函数就形成了闭包,并且拥有了timer变量
- 定时器就是延迟多少秒后执行一次,也有循环定时器和立即执行器;
- apply函数可以理解为替调用者传递一个作用域
this指向
,及参数列表,属于javascript的高阶函数,这里我推荐一个学习文章:apply函数
介绍完了以上技术,我再以我的理解叙述下这个函数的执行特征:
- debounce函数在调用后会返回一个带有定时器的函数
- 这个函数在一定时间后执行,也就是我们的delay参数
- 这个函数在执行时会调用传入的fn函数
为什么调用fn函数需要使用apply来改变this指向呢?
帅气的人回答:这就与我们需要防抖的场景密切相关,例如input事件,该事件会执行一个传入的函数,并且附带回调参数event; 如果不用apply,那防抖函数的作用域里就访问不到这俩个最有用的东西了。
下面看我的例子
let input = document.getElementById('input');
input.addEventListener('input',debounce(search,1000))
//防抖回调执行函数,这个函数在防抖函数执行后,根据delay执行
function search(e){
console.log(e); //这里可以拿到e,要归功于apply的arguments参数
console.log(this);//这里可以拿到this,要归功于apply的this参数
this.style.padding="20px";
}
//防抖
function debounce(fn, delay = 300) {
// delay 秒后执行一次
let timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
//this:让函数获得调用者的指向
//arguments:函数的参数,由于此处无法断言
//故用argument
fn.apply(this, arguments);
}, delay)
}
}
fn.apply(this, arguments);
这里的this到底是谁的this? 这是我最大的疑问,也是发这篇文章最想说的话,谁最后一次调用的debounce This就是谁的,我们绑定的是input的事件,那input调用的回调函数,this就是input的。
再来给大家看下效果:
另外我把节流的代码段附上,理念相同只是在控制上有所区别,大家可以根据需求扩展函数
//节流
function throttle(fn, delay = 300) {
// delay 秒内执行一次
let flag = true;
return function () {
if (!flag) return;
flag = false
setTimeout(() => {
fn.apply(this, arguments);
flag = true
}, delay);
}
}
看到这里,如果你理解了,你将会对apply函数应用,闭包函数,有更好的理解,相关于apply函数的还有call(),bind()等高阶函数,均属于一个类型,但是它们的使用场景不同,这里不再扩展。
最后
???? javascript专栏
☃️ 个人简介:一个喜爱技术,喜欢探索的人。
???? 励志格言: 脚踏实地,虚心学习,相信自己的配得上所有美好。
❗如果文章还可以,记得用你可爱的小手点赞????关注✅,我会在第一时间回关。