简单实现节流函数和防抖函数过程解析_javascript技巧

来源:脚本之家  责任编辑:小易  

C程序的基本单元是函数。函数中包含了程序的可执行代码。每个C程序的入口和出口都位于函数main()之中。main()函数可以调用其他函数,这些函数执行完毕后程序的控制又返回到main()函数中,main()函数不能被别的函数所调用。通常我们把这些被调用的函数称为下层(lower-level)函数。函数调用发生时,立即执行被调用的函数,而调用者则进入等待状态,直到被调用函数执行完毕。函数可以有参数和返回值。程序员一般把函数当作“黑箱”处理,并不关心它内部的实现细节。当然程序员也可以自己开发函数库。说明一点,函数这一节很重要,可以说一个程序的优劣集中体现在函数上。如果函数使用的恰当,可以让程序看起来有条理,容易看懂。如果函数使用的乱七八糟,或者是没有使用函数,程序就会显得很乱,不仅让别人无法查看,就连自己也容易晕头转向。可以这样说,如果超过100行的程序中没有使用函数,那么这个程序一定很罗嗦(有些绝对,但也是事实)。一、函数的定义一个函数包括函数头和语句体两部分。函数头由下列三不分组成:函数返回值类型函数名参数表一个完整的函数应该是这样的:函数返回值类型 函数名(参数表){语句体;}函数返回值类型可以是前面说到的某个数据类型、或者是某个数据类型的指针、指向结构的指针、指向数组的指针。指针概念到以后再介绍。函数名在程序中必须是唯一的,它也遵循标识符命名规则。参数表可以没有也可以有多个,在函数调用的时候,实际参数将被拷贝到这些变量中。语句体包括局部变量的声明和可执行代码。我们在前面其实已经接触过函数了,如abs(),sqrt(),我们并不知道它的内部是什么,我们只要会使用它即可。下面主要介绍无参数无返回值的函数调用。二、函数的声明和调用为了调用一个函数,必须事先声明该函数的返回值类型和参数类型,这和使用变量的道理是一样的(有一种可以例外,就是函数的定义在调用之前,下面再讲述)。看一个简单的例子:void a();函数声明*/main(){a();函数调用*/}void a()/*函数定义*/{int num;scanf(%d,&num);printf(%d\\n,num);}在main()的前面声明了一个函数,函数类型是void型,函数名为a,无参数。然后在main()函数里面调用这个函数,该函数的作用很简单,就是输入一个整数然后再显示它。在调用函数之前声明了该函数其实它和下面这个程序的功能是一样的:main(){int num;scanf(%d,&num);printf(%d\\n,num);}可以看出,实际上就是把a()函数里面的所有内容直接搬到main()函数里面(注意,这句话不是绝对的。我们前面已经说了,当定义在调用之前时,可以不声明函数。所以上面的程序和下面这个也是等价的:void a(){int num;scanf(%d,&num);printf(%d\\n,num);}main(){a();}因为定义在调用之前,所以可以不声明函数,这是因为编译器在编译的时候,已经发现a是一个函数名,是无返回值类型无参数的函数了。那么很多人也许就会想,那我们何必还要声明这一步呢?我们只要把所有的函数的定义都放在前面不就可以了吗?这种想法是不可取的,一个好的程序员总是在程序的开头声明所有用到的函数和变量,这是为了以后好检查。前面说了,在调用之前,必须先声明函数,所以下面的做法也是正确的(但在这里我个人并不提倡)。main(){void a();a();}void a(){int num;scanf(%d,&num);printf(%d\\n,num);}一般来说,比较好的程序书写顺序是,先声明函数,然后写主函数,然后再写那些自定义的函数。既然main()函数可以调用别的函数,那么我们自己定义的函数能不能再调用其他函数呢?答案是可以的。看下面的例子:void a();void b();main(){a();}void a(){b();}void b(){int num;scanf(%d,&num);printf(%d\\n,num);}main()函数先调用a()函数,而a()函数又调用b()函数。在C语言里,对调用函数的层数没有严格的限制,我们可以往下调用100层、1000层,但是在这里我们并不提倡调用的层数太多(除非是递归),因为层数太多,对以后的检查有一些干扰,函数调过来调过去,容易让自己都晕头转向。某些人可能就不明白了,看上面的例子,好象使用函数后,程序变的更长了,更不让人理解。当然,我举的这个例子的确没有必要用函数来实现,但是对于某些实际问题,如果不使用函数,会让程序变的很乱,这涉及到参数问题www.zgxue.com防采集请勿采集本网。

在日常开发中有很多场景我们都需要用到节流函数和防抖函数,比如:实现输入框的模糊查询因为需要轮询ajax,影响浏览器性能,所以需要用到节流函数;实现手机号、姓名之类的的验证,往往我们只需要验证一次,这个时候我们就需要用到防抖函数;但是网上的很多资料都是不够具体和便于理解。今天自己翻阅了一些资料之后,来简单的谈谈我对节流函数和防抖函数的理解,希望能帮助大家理解;

在Windows中,所有的消息均通过窗口过程函数进行处理,窗口过程函数是我们和Windows操作系统建立联系的唯一途径,窗口过程函数的声明均为: LRESULT_stdcall WndProc (HWND hWnd,UINT msg,WPARAM

节流函数

if语句的一般形式百如下: if(表达式)语句1 [else语句2] if语句中的“表达度式”可以是关系表达式、逻辑表达式,甚至是数值表达式。其中最直观、最容易理解的是关系表达式。

顾名思义,就是节省流量节省内存性能的一种函数,可以理解为是一种性能优化方案;

我给你简单写了一个经典的递归函数(求阶乘) include int fun(int n) { printf(\"test.\\n\");先帮助你理解7a686964616fe58685e5aeb931333262356164递归的基本过程 if(n=0) return 1;else return n

举个例子:一个水龙头一直在滴水,可能一次性会滴很多水,但是我们想控制它的频率 ,让它每1000毫秒滴一滴水,这个时候我们就可以用到节流函数来进行控制(简单可以理解为类似于周期性定时器)

目前2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。

js代码(可直接复制到编辑器上看效果):

rand函数是根据一个数(我们可以称它为种子)为基准,以某个递推公式推算出来的一系数,当这系列数很大的时候,就符合正态公布,从而相当于产生了随机数, 但这产生的并不是真意正义上的随机数,

//首先定义一个全局变量var canRun = true;//当浏览器窗口大小发生变化也就是重新计算窗口大小的时候触发window.onresize = function(){// 取反,canRun为false的情况下if(!canRun){//直接return,后面的代码不执行 return}//走到这来就是canRun为true的情况,然后进行赋值为falsecanRun = false//设置一个定时器进行轮询操作setTimeout( function () {//这是要做的事情 console.log("函数节流")//最后记得重新赋值true继续让他取反 canRun = true//每隔1000毫秒也就是1秒钟就执行一次 }, 1000)}

效果图如下:

防抖函数

防抖函数和节流函数很类似,但是稍有区别,防抖函数的定义是当事件触发完成之后再延迟触发,并且只触发一次;如果在触发完成之前再次触发,则会再次刷新延迟;简单理解为(如果事件不触发即不执行,并且只会执行一次,就是定时器最后走的那一次)

举个例子:假如有个弹簧,你一直往下按压只要你不松手就是不会弹出的,弹簧只有在你松手的那一瞬间才会弹出去;防抖函数也是如此,只要事情触发没有结束是不会执行的,只有在事件触发结束后延迟执行一次;

js代码(可直接复制到编辑器上看效果):

rand函数是根据一个数(我们可以称它为种子)为基准,以某个递推公式推算出来的一系数,当这系列数很大的时候,就符合正态公布,从而相当于产生了随机数, 但这产生的并不是真意正义上的随机数,

//定义方法即要做的事情function fun(){ console.log('onresize') }//定义事件触发要执行的方法,两个参数分别是传入的要做的事情和定时器的毫秒数function debounce(fn,delay){  //定义一个变量作为等会清除对象 var handle;  //这里用到了闭包,一个函数里面return另一个函数,变量相互签引导致垃圾回收机制不会销毁handle变量 return function(){      //在这里一定要清除前面的定时器,然后创建一个新的定时器 clearTimeout(handle)       //最后这个定时器只会执行一次也就是事件触发完成之后延迟500毫秒再触发(这里的变量赋值是跟定时器建立连接,进行地址赋值,一定要重新赋值给handle handle=setTimeout(function(){ fn() },delay) } }//给浏览器添加监听事件resizewindow.addEventListener('resize', debounce(fun, 500));

效果图如下:

总结:

1.防抖函数和节流函数都是用来提升性能优化及用户体验的一种方案;

2.防抖函数只会执行一次,且是最后触发的那一次,而节流函数会规律性的执行多次;

一、概念解释2113函数节流和函数防抖,两者都是5261优化高4102频率执行js代码的一种手1653段。大家大概都知道旧款电视机的工作原理,就是一行行得扫描出色彩到屏幕上,然后组成一张张图片。由于肉眼只能分辨出一定频率的变化,当高频率的扫描,人类是感觉不出来的。反而形成一种视觉效果,就是一张图。就像高速旋转的风扇,你看不到扇叶,只看到了一个圆一样。同理,可以类推到js代码。在一定时间内,代码执行的次数不一定要非常多。达到一定频率就足够了。因为跑得越多,带来的效果也是一样。倒不如,把js代码的执行次数控制在合理的范围。既能节省浏览器CPU资源,又能让页面浏览更加顺畅,不会因为js的执行而发生卡顿。这就是函数节流和函数防抖要做的事。函数节流是指一定时间内js方法只跑一次。比如人的眨眼睛,就是一定时间内眨一次。这是函数节流最形象的解释。函数防抖是指频繁触发的情况下,只有足够的空闲时间,才执行代码一次。比如生活中的坐公交,就是一定时间内,如果有人陆续刷卡上车,司机就不会开车。只有别人没刷卡了,司机才开车。二、函数节流函数节流应用的实际场景,多数在监听页面元素滚动事件的时候会用到。因为滚动事件,是一个高频触发的事件。以下是监听页面元素滚动的示例代码:// 函数节流var canRun = true;document.getElementById("throttle").onscroll = function(){if(!canRun){// 判断是否已空闲,如果在执行中,则直接returnreturn;}canRun = false;setTimeout(function(){console.log("函数节流");canRun = true;}, 300);};函数节流的要点是,声明一个变量当标志位,记录当前代码是否在执行。如果空闲,则可以正常触发方法执行。如果代码正在执行,则取消这次方法执行,直接return。这个方法的作用是监听ID为throttle元素的滚动事件。当canRun为true,则代表现在的滚动处理事件是空闲的,可以使用。通过关卡if(!canRun),等于就拿到了通行证。然后下一步的操作就是立马将关卡关上canRun=false。这样,其他请求执行滚动事件的方法,就被挡回去了。接着用setTimeout规定最小的时间间隔300,接着再执行setTimeout方法体里面的内容。最后,等setTimeout里面的方法都执行完毕,才释放关卡canRun=true,允许下一个访问者进来。这个函数节流的实现形式,需要注意的是执行的间隔时间是>=300ms。如果具体执行的方法是包含callback的,也可以将canRun=true这一步放到callback中。理解了函数节流的关卡设置重点,其实改起来就简单多了。三、函数防抖函数防抖的应用场景,最常见的就是用户注册时候的手机号码验证和邮箱验证了。只有等用户输入完毕后,前端才需要检查格式是否正确,如果不正确,再弹出提示语。以下还是以页面元素滚动监听的例子,来进行解析:// 函数防抖var timer = false;document.getElementById("debounce").onscroll = function(){clearTimeout(timer); // 清除未执行的代码,重置回初始化状态timer = setTimeout(function(){console.log("函数防抖");}, 300);}; 函数节流的要点,也是需要一个setTimeout来辅助实现。延迟执行需要跑的代码。如果方法多次触发,则把上次记录的延迟执行代码用clearTimeout清掉,重新开始。如果计时完毕,没有方法进来访问触发,则执行代码。这个方法的作用是监听ID为debounce元素的滚动事件进入滚动事件方法体的时候,做的第一件事就是清除上次未执行的setTimeout。而setTimeout的引用id由变量timer记录。clearTimeout方法,允许传入无效的值。所以这里直接执行clearTimeout即可。然后,将需要执行的代码放入setTimeout中,再返回setTimeout引用给timer缓存。如果倒计时300ms以后,还没有新的方法触发滚动事件,则执行setTimeout中的代码。函数防抖的实现重点,就是巧用setTimeout做缓存池,而且可以轻易地清除待执行的代码。其实,用队列的方式也可以做到这种效果。这里就不深入了。四、在线demo这是我写的一个测试demo,把鼠标移动到模块上方,滚动滚轮,即可在控制台查看输出效果,函数防抖当调用2113动作过n毫秒后,才会执行该动5261作,若4102在这n毫秒内又调用此动作则将重新1653计算执行时间;要实现的效果是:当高频率调用某个函数时,在停止后执行。函数节流预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期。要实现的效果是:当高频率调用某个函数时,让它按某个特定的频率执行。网上有人形容的很形象:如果一直触发一个事件,函数防抖的方法定义的方法永远不会执行,就像一个水龙头,如果关闭了,永远不会出水;函数分流的方法像一个关闭水龙头不好用,当关闭水龙头隔一段时间会有滴水一样,节流概念(Throttle)按照设定的时间2113固定5261执行一次函数,比如200ms一次。注意:固定就是4102你在mousemove过程中,执行这个1653节流函数,它一定是200ms(你设定的定时器延迟时间)内执行一次。没到200ms,一定会返回,没有执行回调函数的。主要应用场景有:scroll、touchmove防抖概念(Debounce)抖动停止后的时间超过设定的时间时执行一次函数。注意:这里的抖动停止表示你停止了触发这个函数,从这个时间点开始计算,当间隔时间等于你设定时间,才会执行里面的回调函数。如果你一直在触发这个函数并且两次触发间隔小于设定时间,则一定不会到回调函数那一步。·主要应用场景有:input验证、搜索联想、resize节流实现思路: 第一次先设定一个变量true,第二次执行这个函数时,会判断变量是否true,是则返回。当第一次的定时器执行完函数最后会设定变量为flase。那么下次判断变量时则为flase,函数会依次运行。防抖实现思路:首次运行时把定时器赋值给一个变量,第二次执行时,如果间隔没超过定时器设定的时间则会清除掉定时器,重新设定定时器,依次反复,当我们停止下来时,没有执行清除定时器,超过一定时间后触发回调函数。博文有介绍更详细的原理和代码demo:网页链接,希望可以帮到您内容来自www.zgxue.com请勿采集。


  • 本文相关:
  • 一文看懂如何简单实现节流函数和防抖函数
  • 如何解决js函数防抖、节流出现的问题
  • 浅谈vue防抖与节流的最佳解决方案(函数式组件)
  • js函数节流和防抖之间的区分和实现详解
  • js函数节流和函数防抖问题分析
  • javascript函数的节流[throttle]与防抖[debounce]
  • 浅谈js函数节流防抖
  • javascript函数节流和函数防抖之间的区别
  • javascript 匿名函数(anonymous function)与闭包(closure)
  • 解决flash需要点击激活的代码
  • js脚本实现定时到网站上签到/签退功能
  • javascript实现快速排序(quicksort)的算法详解
  • javascript实现asc转汉字及汉字转asc的方法
  • js刷新框架外页面七种实现代码
  • es6通过babel转码使用webpack使用import关键字
  • js判断输入是否为正整数、浮点数等数字的函数代码
  • javascript运动框架 多值运动(四)
  • 浅析javascript中的同名标识符优先级
  • javascript函数节流和函数防抖之间的区别
  • 函数调用过程是怎么实现的
  • 通过定义函数实现冒泡排序过程,
  • 过程与函数有什么区别?
  • 窗口过程到底是怎么实现的?函数代码是什么?
  • c语言 if()函数式如何实现的?
  • 递归函数详细运行过程
  • C语言用函数如何实现两个数交换?
  • c语言里 random函数怎么实现的
  • 在VBA中如何调用过程与函数?
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全基础知识javascript类库表单特效广告代码网页特效黑客性质javascript技巧domnode.jsjs其它首页javascript一文看懂如何简单实现节流函数和防抖函数如何解决js函数防抖、节流出现的问题浅谈vue防抖与节流的最佳解决方案(函数式组件)js函数节流和防抖之间的区分和实现详解js函数节流和函数防抖问题分析javascript函数的节流[throttle]与防抖[debounce]浅谈js函数节流防抖javascript函数节流和函数防抖之间的区别javascript 匿名函数(anonymous function)与闭包(closure)解决flash需要点击激活的代码js脚本实现定时到网站上签到/签退功能javascript实现快速排序(quicksort)的算法详解javascript实现asc转汉字及汉字转asc的方法js刷新框架外页面七种实现代码es6通过babel转码使用webpack使用import关键字js判断输入是否为正整数、浮点数等数字的函数代码javascript运动框架 多值运动(四)浅析javascript中的同名标识符优先级js刷新页面方法大全js中settimeout()的用法详解js截取字符串常用方法详细整理js页面跳转常用的几种方式js打开新窗口的2种方式js数组与字符串的相互转换方法js设置cookie、读取cookie、删除js删除数组里的某个元素方法js 将json字符串转换为json对象的javascript深入理解js闭包公共js在页面底部加载的注意事项介绍ie中js跳转丢失referrer问题的2个解决方法iframe高度自适应及隐藏滚动条的实例详解bootstrap的fileinput插件实现多文件上传ie与firefox下dhtml的一些区别小结js鼠标悬浮出现遮罩层的方法javascript实现的搜索及高亮显示功能示例javascript中的高阶函数介绍js中浮点型运算bug的解决方法说明js实现自动播放匀速轮播图
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved