博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浅谈javascript函数节流
阅读量:4693 次
发布时间:2019-06-09

本文共 3749 字,大约阅读时间需要 12 分钟。

浅谈javascript函数节流

什么是函数节流?

     函数节流简单的来说就是不想让该函数在很短的时间内连续被调用,比如我们最常见的是窗口缩放的时候,经常会执行一些其他的操作函数,比如发一个ajax请求等等事情,那么这时候窗口缩放的时候,有可能连续发多个请求,这并不是我们想要的,或者是说我们常见的鼠标移入移出tab切换效果,有时候连续且移动的很快的时候,会有闪烁的效果,这时候我们就可以使用函数节流来操作。大家都知道,DOM的操作会很消耗或影响性能的,如果是说在窗口缩放的时候,为元素绑定大量的dom操作的话,会引发大量的连续计算,比如在IE下,过多的DOM操作会影响浏览器性能,甚至严重的情况下,会引起浏览器崩溃的发生。这个时候我们就可以使用函数节流来优化代码了~

函数节流的基本原理:

     使用一个定时器,先延时该函数的执行,比如使用setTomeout()这个函数延迟一段时间后执行函数,如果在该时间段内还触发了其他事件,我们可以使用清除方法 clearTimeout()来清除该定时器,再setTimeout()一个新的定时器延迟一会儿执行。

我们先来看一个简单的window.resize的demo例子,比如我先定义一个全局变量count=0;当我触发一次window.resize的时候,该全局变量count++; 我们来看看在控制台中打印出count的效果;JS代码如下:

var count = 0;window.onresize = function(){    count++;    console.log(count);}

执行截图效果如下:

如上resize的代码,简单的缩放一次就打印出多次,这并不是我们想要的效果,这是简单的测试,那如果我们换成ajax请求的话,那么就会缩放一次窗口会连续触发多次ajax请求,下面我们试着使用函数节流的操作试试一下;

函数节流的第一种方案封装如下:

function throttleFunc(method,context){     clearTimeout(method.tId);     method.tId = setTimeout(function(){         method.call(context);     },100); }

我们再来封装一下窗口缩放的demo

var count = 0;function myFunc() {   count++;   console.log(count); } window.onresize = function(){    throttleFunc(myFunc); } function throttleFunc(method,context){     clearTimeout(method.tId);     method.tId = setTimeout(function(){         method.call(context);     },100); }

如上代码,我们再来看看效果,窗口缩放和放大效果会看到,只执行了一次;打印了一次。

上面的代码使用一个定时器每隔100毫秒执行一次;

我们也可以使用闭包的方法对上面的函数进行再封装一下;

函数节流的第二种封装方法如下:

function throttle(fn, delay){     var timer = null;     return function(){         var context = this,              args = arguments;         clearTimeout(timer);         timer = setTimeout(function(){             fn.apply(context, args);         }, delay);     }; };

上面第二种方案是使用闭包的方式形成一个私有的作用域来存放定时器timer,第二种方案的timer是通过传参数的形式引入的。

调用demo代码如下:

var count = 0;function myFunc() {    count++;    console.log(count);}var func = throttle(myFunc,100);window.onresize = function(){   func();}         function throttle(fn, delay){     var timer = null;     return function(){         var context = this,              args = arguments;         clearTimeout(timer);         timer = setTimeout(function(){             fn.apply(context, args);         }, delay);     };};

函数节流的基本思想是:就是想让一个函数不要执行的太频繁,减少一些过快的来节流函数,比如当我们改变窗口缩放的时候,浏览器的间隔有可能是16ms,这是浏览器自带的时间间隔,我们无法改变,而我们通过节流的方式可以试着改变一下这个间隔,尽量稍微延长下这个调用时间,因此我们可以封装如下函数:

函数节流的第三种封装方法

function throttle3(fn,delay,runDelay){      var timer = null;      var t_start;      return function(){         var context = this,             args = arguments,             t_cur = new Date();         timer && clearTimeout(timer);         if(!t_start) {             t_start = t_cur;         }         if(t_cur - t_start >= runDelay) {              fn.apply(context,args);              t_start = t_cur;         }else {              timer = setTimeout(function(){                  fn.apply(context,args);               },delay);         }    }}

调用demo如下:

var count = 0;function myFunc() {   count++;   console.log(count);}var func = throttle3(myFunc,50,100);window.onresize = function(){   func(); } function throttle3(fn,delay,runDelay){      var timer = null;      var t_start;      return function(){          var context = this,              args = arguments,              t_cur = new Date();          timer && clearTimeout(timer);          if(!t_start) {              t_start = t_cur;          }          if(t_cur - t_start >= runDelay) {                fn.apply(context,args);                t_start = t_cur;          }else {                timer = setTimeout(function(){                     fn.apply(context,args);                },delay);          }      }}

上面的第三个函数是封装后的函数,有三个参数,我们可以自己设置触发事件的时间间隔,则意味着,如上代码50ms连续调用函数,后一个调用会把前一个调用的等待处理掉,但每隔100ms会至少执行一次,具体使用哪一种方式只要看自己的权衡,但是我个人觉得第二种封装函数的方式够我们使用的,当然据说第三种方式性能更好~

转载于:https://www.cnblogs.com/tugenhua0707/p/5272539.html

你可能感兴趣的文章
第二节 整型数据
查看>>
Python 序列
查看>>
Liferay的架构:缓存(第一部分)
查看>>
初识B/S结构编程技术
查看>>
方法、hadoop源码之JobQueueTaskScheduler-by小雨
查看>>
页面重构总结
查看>>
IO 函数
查看>>
Unity V3 初步使用 —— 为我的.NET项目从简单三层架构转到IOC做准备
查看>>
JSP页面间传递参数
查看>>
VSNETcodePrint 2005 & SQL ServerPrint 2005
查看>>
java数组基本操作
查看>>
String的indexOf()用于获取字符串中某个子字符串的位置
查看>>
shell 脚本运算符
查看>>
又一道软通动力7K月薪面试题——银行业务调度系统
查看>>
Matlab画图-非常具体,非常全面
查看>>
ReactJS入门
查看>>
linux网站配置文件.htaccess伪静态转换到IIS web.config中
查看>>
CodeForces 1B
查看>>
win10应用UserControl
查看>>
BZOJ4516: [Sdoi2016]生成魔咒(后缀自动机)
查看>>