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 相关文章推荐
javascript 二进制运算技巧解析
Nov 27 Javascript
鼠标移动到图片名上,显示图片的简单实例
Jul 14 Javascript
JS给Textarea文本框添加行号的方法
Aug 20 Javascript
jQuery实现的网页竖向菜单效果代码
Aug 26 Javascript
JS实现复制内容到剪贴板功能兼容所有浏览器(推荐)
Jun 17 Javascript
深入理解Node.js的HTTP模块
Oct 12 Javascript
浅谈jquery之on()绑定事件和off()解除绑定事件
Oct 26 Javascript
vue 2.0组件与v-model详解
Mar 27 Javascript
JS+HTML5 FileReader对象用法示例
Apr 07 Javascript
详解在Angularjs中ui-sref和$state.go如何传递参数
Apr 24 Javascript
在Vue中使用Viser说明(基于AntV-G2可视化引擎)
Oct 28 Javascript
VUE递归树形实现多级列表
Jul 15 Vue.js
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
合作指挥官:孟斯克
2020/03/16 星际争霸
php debug 安装技巧
2011/04/30 PHP
PHP手机号中间四位用星号*代替显示的实例
2017/06/02 PHP
javascript中this做事件参数相关问题解答
2013/03/17 Javascript
动态加载script文件的两种方法
2013/08/15 Javascript
浅谈JavaScript函数参数的可修改性问题
2013/12/05 Javascript
jQuery实现订单提交页发送短信功能前端处理方法
2016/07/04 Javascript
JS简单获取客户端IP地址的方法【调用搜狐接口】
2016/09/05 Javascript
JavaScript基本类型值-Undefined、Null、Boolean
2017/02/23 Javascript
bootstrap table实现x-editable的行单元格编辑及解决数据Empty和支持多样式问题
2017/08/10 Javascript
Angular将填入表单的数据渲染到表格的方法
2017/09/22 Javascript
js 开发之autocomplete=&quot;off&quot;在chrom中失效的解决办法
2017/09/28 Javascript
在axios中使用params传参的时候传入数组的方法
2018/09/25 Javascript
layui实现下拉框三级联动
2019/07/26 Javascript
Node使用Nodemailer发送邮件的方法实现
2020/02/24 Javascript
用Python从零实现贝叶斯分类器的机器学习的教程
2015/03/31 Python
Python中的index()方法使用教程
2015/05/18 Python
python抓取百度首页的方法
2015/05/19 Python
Python基于time模块求程序运行时间的方法
2017/09/18 Python
Sanic框架Cookies操作示例
2018/07/17 Python
Python多进程与服务器并发原理及用法实例分析
2018/08/21 Python
python实现对任意大小图片均匀切割的示例
2018/12/05 Python
详解python执行shell脚本创建用户及相关操作
2019/04/11 Python
PyInstaller将Python文件打包为exe后如何反编译(破解源码)以及防止反编译
2020/04/15 Python
纯CSS3编写的的精美动画进度条(无flash/无图像/无脚本/附源码)
2013/01/07 HTML / CSS
无需JS和jQuery代码实现CSS3鼠标浮动放大图片
2016/11/21 HTML / CSS
HTML5在canvas中绘制复杂形状附效果截图
2014/06/23 HTML / CSS
美国折扣香水网站:The Perfume Spot
2020/12/12 全球购物
介绍一下XMLHttpRequest对象的常用方法和属性
2013/05/24 面试题
学雷锋志愿服务月活动总结
2014/03/09 职场文书
疾病捐款倡议书
2014/05/13 职场文书
2014年学生会部门工作总结
2014/11/07 职场文书
荆州古城导游词
2015/02/06 职场文书
运动会开幕式通讯稿
2015/07/18 职场文书
使用python绘制横竖条形图
2022/04/21 Python
从原生JavaScript到React深入理解
2022/07/23 Javascript