函数防抖和节流是什么?怎样实现和使用?
Admin 2021-10-21 群英技术资讯 1507 次浏览
本文给大家介绍的是函数防抖和函数节流,本文会给大家详细的介绍函数防抖和节流是什么,以及如何实现和使用场景等等,下文还有示例供大家参考,感兴趣的朋友就继续往下看吧。
概念:函数防抖(debounce),就是指触发事件后,在 n 秒内函数只能执行一次,如果触发事件后在 n 秒内又触发了事件,则会重新计算函数延执行时间。
前端开发过程中,有一些事件,常见的例如,onresize,scroll,mousemove ,mousehover 等,会被频繁触发(短时间内多次触发),不做限制的话,有可能一秒之内执行几十次、几百次,如果在这些函数内部执行了其他函数,尤其是执行了操作 DOM 的函数(浏览器操作 DOM 是很耗费性能的),那不仅会浪费计算机资源,还会降低程序运行速度,甚至造成浏览器卡死、崩溃。
函数防抖的要点,是需要一个 setTimeout 来辅助实现,延迟运行需要执行的代码。如果方法多次触发,则把上次记录的延迟执行代码用 clearTimeout 清掉,重新开始计时。若计时期间事件没有被重新触发,等延迟时间计时完毕,则执行目标代码。
//HTML部分
<div>
账户:<input type="text" id="myinput">
</div>
//JS部分
function debounce(fun,wait=1500){//ES6语法 wait=1500 设置参数默认值,如果没有输入wait就会使用1500
let timeout = null
return function(){
if(timeout){//如果存在定时器就清空
clearTimeout(timeout)
}
timeout=setTimeout(function(){
fun()
},wait)
}
}
function testUname(){
console.log("输入结束!")
}
document.getElementById('myinput').addEventListener('input',debounce(testUname,1000))

上面的代码就是防抖函数的简单运用,只要你每次输入间隔大于一秒,那么永远不会打“印输入结束!”,直到你停止输入吗,这是因为每一次的输入都会清除上一次的计时器。
看到这里你以为就结束了吗?别急,让我们继续看:
//HTML部分
<div>
账户:<input type="text" id="myinput">
</div>
//JS部分
function debounce(fun,wait=1500){
let timeout = null
return function(){
console.log(this)//<input id="myinput" type="text">
console.log(arguments)//Arguments { 0: input, … }
if(timeout){//如果存在定时器就清空
clearTimeout(timeout)
}
timeout=setTimeout(function(){
console.log(this)//Window
console.log(arguments)//Arguments { … }
fun()
},wait)
}
}
function testUname(){
console.log("输入结束!")
}
document.getElementById('myinput').addEventListener('input',debounce(testUname,1000))
无论是防抖还是节流,我们都要解决两个问题,this指向和arguments。
如果没有特殊指向,setInterval和setTimeout的回调函数中this的指向都是window。这是因为JS的定时器方法是定义在window下的。这显然不是我们希望的,因为我们监听的是input输入框,所以我们希望定时器里面的this指向input。
那么有什么方法可以改变this指向吗?
一种简单的办法就是我们可以用参数把定时器外层函数的this和arguments保存下来。然后再通过apply改变定时器要执行的函数fun的指向。
//JS部分
function debounce(fun,wait=1500){
let timeout = null
return function(){
let _this = this
let arg = arguments
if(timeout){//如果存在定时器就清空
clearTimeout(timeout)
}
timeout=setTimeout(function(){
console.log(_this)//<input id="myinput" type="text">
console.log(arg)//Arguments { 0: input, … }
fun.apply(_this,arg)
},wait)
}
}

当然,你也可以用ES6的箭头函数新特性:箭头函数的 this 始终指向函数定义时的 this,而非执行时。箭头函数需要记着这句话:“箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值,如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this,否则,this 为 undefined”。
所以也可以这样写:
//JS部分
function debounce(fun,wait=1500){
let timeout = null
return function(){
if(timeout){//如果存在定时器就清空
clearTimeout(timeout)
}
timeout=setTimeout(()=>{
console.log(this)//<input id="myinput" type="text">
console.log(arguments)//Arguments { 0: input, … }
fun.apply(this,arguments)
},wait)
}
}

函数防抖一般用在什么情况之下呢?一般用在,连续的事件只需触发一次回调的场合。具体有:
概念: 限制一个函数在一定时间内只能执行一次。
举个栗子,坐火车或地铁,过安检的时候,在一定时间(例如10秒)内,只允许一个乘客通过安检入口,以配合安检人员完成安检工作。上例中,每10秒内,仅允许一位乘客通过,分析可知,“函数节流”的要点在于,在 一定时间 之内,限制 一个动作 只 执行一次 。
主要实现思路就是通过 setTimeout 定时器,通过设置延时时间,在第一次调用时,创建定时器,先设定一个变量,然后把定时器赋值给这个变量,再写入需要执行的函数。第二次执行这个函数时,会判断变量是否true,是则返回。当第一次的定时器执行完函数最后会设定变量为false。那么下次判断变量时则为false,函数会依次运行。目的在于在一定的时间内,保证多次函数的请求只执行最后一次调用。
这么看是不是有点看不懂?让我们来看代码:
//JS部分
function debounce(fun,wait=1000){//定时器方案
let timer = null;//先设定一个变量
return function(){
if(!timer){//如果timer为null就进入
timer = setTimeout(function(){//然后把定时器赋值给这个变量
fun()//再写入需要执行的函数
timer = null//第一次的定时器执行完函数最后会设定变量为false,这里的 timer = null有两个作用,
//1、开启下一次的入口,2、清除后面的定时器
})
}
}
}
function testUname(){
console.log(Math.random())
}
document.getElementById('myinput').addEventListener('input',debounce(testUname))

同样的,节流函数也要解决this和arguments的问题,改进后如下:
//箭头函数写法
function debounce(fun,wait=1000){
let timer = null
return function(){
if(!timer){
timer = setTimeout(()=>{
fun.apply(this,arguments)
timer = null
},wait)
}
}
}
//参数保存法
function debounce(fun,wait=1000){
let timer = null
return function(){
let _this = this
let arg = arguments
if(!timer){
timer = setTimeout(function(){
fun.apply(_this,arg)
timer = null
},wait)
}
}
}
到此为止,相信各位应该对函数节流有了一个比较详细的了解,那函数节流一般用在什么情况之下呢?
关于函数防抖和节流的内容就介绍到这,本文对大家学习和理解函数防抖和节流有一定的帮助,需要的朋友可以参考。想要了解更多函数防抖和节流的内容,大家可以关注其它的相关文章。
文本转载自脚本之家
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
经历过一些列的函数式编程思想的学习总结,一些重要的高阶函数的学习,以及前一段时间关于 RxJS 的学习。我们再回看一次 —— 组合函数 compose本瓜越来越觉得,【易读】的代码应该是将声明和调用分开来的。根据不同的流程,用函数组合的方式、也可以说它是管道、或者说是链式调用,将声明的函数组合起来,再等待时机进行调用。
这篇文章主要为大家介绍了JavaScript之instanceof方法手写示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
本篇文章给大家带来了关于javascript的相关知识,其中主要整理了处理树状结构数据的增删改查的相关问题,相比普通的数组结构数据,树状结构的处理就没有数组那么的直观,但是也没那么复杂,需要多一步递归查找来对数据进行深度遍历操作,下面一起来看一下,希望对大家有帮助。
Array.from可以从类似的数组或可迭代对象中创建一个新的、浅拷贝的数组实例。Array.from接收三个参数:必须选择类似数组的对象、加工函数、this作用域。
node后台框架有:1、Koa,一个开源的Node web框架,用Generator来实现中间件的流程控制,用try/catch来增强异常处理;2、Nest,一个用于构建高效、可扩展的Node服务器端应用程序的框架;3、Socket,是用来在客户端和服务器端之间创建实时双向通信的框架;4、Sails,是一个非常稳固的Node框架,提供建立任何规模的Web应用所需要的所有功能。
成为群英会员,开启智能安全云计算之旅
立即注册关注或联系群英网络
7x24小时售前:400-678-4567
7x24小时售后:0668-2555666
24小时QQ客服
群英微信公众号
CNNIC域名投诉举报处理平台
服务电话:010-58813000
服务邮箱:service@cnnic.cn
投诉与建议:0668-2555555
Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 ICP核准(ICP备案)粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008