JavaScript函数节流概念与用法实例详解


Posted in Javascript onJune 20, 2016

本文实例讲述了JavaScript函数节流概念与用法。分享给大家供大家参考,具体如下:

最近在做网页的时候有个需求,就是浏览器窗口改变的时候需要改一些页面元素大小,于是乎很自然的想到了window的resize事件,于是乎我是这么写的

<!DOCTYPE html>
<html>
<head>
  <title>Throttle</title>
</head>
<body>
  <script type="text/javascript">
    n=0;
    function resizehandler(){
      console.log(new Date().getTime());
      console.log(++n);
    }
    window.onresize=resizehandler;
  </script>
</body>
</html>

功能倒是实现了,但是我拖拽的方式改变浏览器窗口大小的时候看了下控制台

JavaScript函数节流概念与用法实例详解

没错,简单的一个拖拽让我的resizeHandler()方法执行了52次,这完全不是我想要的效果,实际上我的resizeHandler()方法的代码很复杂,甚至会使用ajax向服务器发送请求,要是简单的一次改变窗口大小就要调用52次这还了得

函数节流

其实我的本意只是窗口resize后页面做一些调整就可以,而window的resize事件并不是在resize结束后才触发的,具体则么个频率我也不知道,但却是在不停的调用,直到窗口大小不再变化。其实类似的机制还有鼠标的mousemove,都是在短时间内重复触发。

在《JavaScript高级程序设计》中有专门应对此问题的函数节流

function throttle(method,context){
  clearTimeout(method.tId);
  method.tId=setTimeout(function(){
    method.call(context);
  },500);
}

原理很简单,利用定时器,让函数执行延迟500毫秒,在500毫秒内如果有函数又被调用则删除上一次调用,这次调用500毫秒后执行,如此往复。这样我刚才的代码可以改为

<script type="text/javascript">
n=0;
function resizehandler(){
  console.log(new Date().getTime());
  console.log(++n);
}
function throttle(method,context){
  clearTimeout(method.tId);
  method.tId=setTimeout(function(){
    method.call(context);
  },500);
}
window.onresize=function(){
  throttle(resizehandler,window);
};
</script>

拖拽一下试试,果真只执行了一次

JavaScript函数节流概念与用法实例详解

另一种做法

网上还有一种函数节流方案,它是这么做的

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

调用一下试试,一样的效果

<script type="text/javascript">
n=0;
function resizehandler(){
  console.log(new Date().getTime());
  console.log(++n);
}
function throttle(method,delay){
  var timer=null;
  return function(){
    var context=this, args=arguments;
    clearTimeout(timer);
    timer=setTimeout(function(){
      method.apply(context,args);
    },delay);
  }
}
window.onresize=throttle(resizehandler,500);//因为返回函数句柄,不用包装函数了
</script>

JavaScript函数节流概念与用法实例详解

比较

两种方法都是利用了setTimeout,不同的是第二种方法加入的函数延迟执行时间,这个在第一种方案中很容易也具有此功能,加一个参数的事儿。

但第一种方案把tId设为函数的一个变量保存,而第二种创建了一个闭包来存储。个人觉得差距不大,很喜欢第一种,简单,高效。

新需求

有一天做了个类似的东西,就像百度首页输入自动提示一样的东西,我在text上绑定keyup事件,每次键盘弹起的时候自动提示,但是又不想提示那么频繁,于是我用了上面方法,但是悲剧了,只有停止输入等500毫秒才会提示,在输入过程中根本就没有提示。看了一下代码,可不是嘛,只要是用户会盲打,在500毫秒内按一下键盘,提示函数就会不断被延迟,这样只有停下来的时候才会提示,这就没意义了。

能不能在函数节流的基础上间隔固定时间就执行一次?

小改动

在网上搜了一下我们可以根据第二种写法(第一种为函数拓展多个变量感觉有些不好)做些改动,添加一个参数作为到固定间隔必须执行

function throttle(method,delay,duration){
  var timer=null, begin=new Date();
  return function(){
    var context=this, args=arguments, current=new Date();;
    clearTimeout(timer);
    if(current-begin>=duration){
       method.apply(context,args);
       begin=current;
    }else{
      timer=setTimeout(function(){
        method.apply(context,args);
      },delay);
    }
  }
}

这样每次我们判断间隔了多久,要是超过设置时间则立即执行一次,以刚才例子试一试效果

window.onresize=throttle(resizehandler,100,200);

JavaScript函数节流概念与用法实例详解

果真既没有频繁执行也没有就最后执行

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
一个简单的瀑布流效果(主体形式自写)
May 27 Javascript
使用js的replace()方法查找字符示例代码
Oct 28 Javascript
js改变Iframe中Src的方法
May 05 Javascript
使用JQuery FancyBox插件实现图片展示特效
Nov 16 Javascript
bootstrap布局中input输入框右侧图标点击功能
May 16 Javascript
Jquery Easyui选项卡组件Tab使用详解(10)
Dec 18 Javascript
jQuery实现的省市联动菜单功能示例【测试可用】
Jan 13 Javascript
Bootstrap学习笔记之进度条、媒体对象实例详解
Mar 09 Javascript
利用SpringMVC过滤器解决vue跨域请求的问题
Feb 10 Javascript
浅谈在Vue.js中如何实现时间转换指令
Jan 06 Javascript
antd vue 刷新保留当前页面路由,保留选中菜单,保留menu选中操作
Aug 06 Javascript
原生JS实现京东查看商品点击放大
Dec 21 Javascript
Angular的Bootstrap(引导)和Compiler(编译)机制
Jun 20 #Javascript
jquery通过name属性取值的简单实现方法
Jun 20 #Javascript
jQuery模拟select实现下拉菜单功能
Jun 20 #Javascript
对jQuary选择器的全面总结
Jun 20 #Javascript
jQuery实现的可编辑表格完整实例
Jun 20 #Javascript
jQuery文件上传控件 Uploadify 详解
Jun 20 #Javascript
javascript js 操作数组 增删改查的简单实现
Jun 20 #Javascript
You might like
php MYSQL 数据备份类
2009/06/19 PHP
php修改指定文件后缀的方法
2014/09/11 PHP
Add Formatted Data to a Spreadsheet
2007/06/12 Javascript
Js 时间函数getYear()的使用问题探讨
2013/04/01 Javascript
JavaScript字符串对象toLowerCase方法入门实例(用于把字母转换为小写)
2014/10/17 Javascript
无刷新上传文件并返回自定义值
2015/06/11 Javascript
基于jQuery+PHP+Mysql实现在线拍照和在线浏览照片
2015/09/06 Javascript
浅谈JavaScript中变量和函数声明的提升
2016/08/09 Javascript
在 Angular2 中实现自定义校验指令(确认密码)的方法
2017/01/23 Javascript
node.js连接MongoDB数据库的2种方法教程
2017/05/17 Javascript
使用重写url机制实现验证码换一张功能
2017/08/01 Javascript
js基于FileSaver.js 浏览器导出Excel文件的示例
2017/08/15 Javascript
anime.js 实现带有描边动画效果的复选框(推荐)
2017/12/24 Javascript
Angular 向组件传递模板的两种方法
2018/02/23 Javascript
详解VUE-地区选择器(V-Distpicker)组件使用心得
2018/05/07 Javascript
Bootstrap table中toolbar新增条件查询及refresh参数使用方法
2018/05/18 Javascript
element-ui 关于获取select 的label值方法
2018/08/24 Javascript
Vuepress 搭建带评论功能的静态博客的实现
2019/02/17 Javascript
vue项目中使用scss的方法步骤
2019/05/16 Javascript
vue解决使用$http获取数据时报错的问题
2019/10/30 Javascript
JavaScript实现多个物体同时运动
2020/03/12 Javascript
[43:32]2014 DOTA2华西杯精英邀请赛 5 25 LGD VS NewBee第一场
2014/05/26 DOTA
[51:43]OG vs LGD 2018国际邀请赛淘汰赛BO3 第五场 8.26
2018/08/30 DOTA
Python下的Softmax回归函数的实现方法(推荐)
2017/01/26 Python
解决.ui文件生成的.py文件运行不出现界面的方法
2019/06/19 Python
Python 实现的 Google 批量翻译功能
2019/08/26 Python
详解Python3 pandas.merge用法
2019/09/05 Python
python tqdm 实现滚动条不上下滚动代码(保持一行内滚动)
2020/02/19 Python
matlab中imadjust函数的作用及应用举例
2020/02/27 Python
Python图像处理之膨胀与腐蚀的操作
2021/02/07 Python
Free People中国官网:波西米亚风格女装服饰
2016/08/30 全球购物
印尼旅游网站:via
2017/11/12 全球购物
餐饮采购员岗位职责
2014/03/15 职场文书
检讨书格式
2015/01/23 职场文书
2015年审计人员工作总结
2015/05/26 职场文书
企业管理制度设计时要注意的几种“常见病”!
2019/04/19 职场文书