背景:在前端开发中,有时会为页面绑定resize事件,或为一个页面元素拖拽事件(其核心就是绑定mousemove)在一个正常操作中也有可能在一个短时间内触发非常多次事件绑定程序,而DOM操作是很消耗性能的,如果为这些事件绑定一些操作DOM节点的操作的话就会引发大量的计算,在用户看来页面可能就一时间没有响应,这个页面就变卡变慢了,甚至在IE下,如果绑定的resize事件进行较多DOM操作,其高频率可能直接就使得浏览器崩溃。
函数节流简单讲就是让一个函数无法在很短的时间间隔内连续调用,只有当上一次函数执行后过了你规定的时间间隔,才能进行下一次该函数的调用。
函数节流原理:用定时器,当触发一个事件时,先setTimout让这个事件延迟一会再执行,如果在这个时间间隔内又触发了事件,那我们就clear掉原来的定时器,再setTimeout一个新的定时器延迟一会执行。
优缺点:
《JavaScript高级程序设计》中介绍的函数节流

function throttle(method,context){
clearTimeout(method,tId);
method.tId=setTimeout(function(){
method.call(context);
},100);
}
//调用
window.onresize=function(){
throttle(myFunc);
} //法二:
var throttle=function(fn,delay){
var timer=null;
return function(){
var context=this,args=arguments;
clearTimeout(timer);
timer=setTimeout(function(){
fn.apply(context,args);//context调用fn的方法,指针指向了fn
},delay);
}
}
//调用
window.onresize=throttle(myFunc,100);

函数节流让一个函数只有在你不断触发后停下来歇会才开始执行,中间你操作得太快它直接无视你。这样做就有点太绝了,resize一般还好,但假如写一个拖拽元素位置的程序,然后直接使用函数节流,会发现你拖动时元素是不动的,你拖完了它直接闪到终点去,所以进行优化:

var throttleV2=function(fn,delay,mustRunDelay){
var timer=null;
var t_start;
return function(){
var context=this,args=arguments,t_curr=+new Date();
clearTimeout(timer);
if(!s_start){
t_start=t_curr;
}if(t_curr-t_start>=mustRunDelay){
fn.apply(context,args);
t_start=t_curr;
}else{
timer=setTimeout(function(){
fn.apply(context,args);
},delay);
}
}
}
window.onresize=throttleV2(myFunc,50,100);

解析:50ms的间隔内连续触发的调用,后一个调用会把前一个调用的等待处理掉,但每隔100ms至少执行一次。
1.具有节流效果的tab切换案例:

var timer=null;
function tab(obj){
var target = document.getElementById(obj);
var spans = target.getElementsByTagName("span");
var lis = target.getElementsByTagName("li");
for(var i=0;i<spans.length;i++)
{ spans[i].onmouseover = function(num){
return function(){
clearTimeout(timer);
timer=setTimeout(function(){
for(var j=0; j<spans.length;j++)
{
spans[j].className = "";
lis[j].className = "";
}
spans[num].className = "current";
lis[num].className = "show";
},300);
}
}(i);
spans[i].onmouseout=function(){
clearTimeout(timer);
}
} }
tab("one");

2.屏幕缩放节流案例:

<body>
<div id="demo"></div>
</body>
</html>
<script>
var demo=document.getElementById("demo");
var num=0;
window.onresize=throll(function(){
demo.innerHTML=window.innerWidth || document.documentElement.clientWidth;
num++;
alert(num);
},300);
function throll(fn,delay){
var timer=null;
return function(){
clearTimeout(timer);
timer=setTimeout(fn,delay);
}
}
</script>

最新文章

  1. php变量-单引号不编译,双引号编译
  2. 一步一步HTML5粒子编辑器
  3. Android Couldn&#39;t load BaiduMapSDK
  4. 使用hbuilder编辑器实现移动app打包
  5. JS的预编译和执行顺序 详析(及全局与局部变量)
  6. Java api 入门教程 之 JAVA的String 类
  7. 无法连接windows虚拟机oracle的解决办法
  8. python学习笔记整理——字典
  9. Gradle tip #2: understanding syntax
  10. 零基础学习云计算及大数据DBA集群架构师【企业级运维技术及实践项目2015年1月29日周五】
  11. .NET系统架构改造的经验和教训
  12. C++ Primer 学习笔记_53_类和数据抽象 --友元、static员
  13. [OpenCV]拓展图像边界
  14. 2_Linux操作系统和基础命令行
  15. 深入理解Plasma(一)Plasma 框架
  16. [LeetCode&amp;Python] Problem 504. Base 7
  17. mathML如何在谷歌浏览器进行展示
  18. 【iCore4 双核心板_ARM】例程七:WWDG看门狗实验——复位ARM
  19. 机器学习之scikit-learn库的使用
  20. Linux的内存分页管理【转】

热门文章

  1. 支持断线重连、永久watcher、递归操作并且能跨平台(.NET Core)的ZooKeeper异步客户端
  2. 【51Nod 1501】【算法马拉松 19D】石头剪刀布威力加强版
  3. Ubuntu 14.04 无线网卡驱动安装
  4. 适配iOS10及Xcode8
  5. bzoj 3262 陌上花开
  6. SpringBoot源码分析:spring的基本架构
  7. Linux命令:查看登录用户
  8. Nodejs - 如何用 eventproxy 模块控制并发
  9. MlLib--逻辑回归笔记
  10. Java学习笔记13---一个循环程序的设计范例