JavaScript函数节流(throttle)与函数去抖(debounce)
对于浏览器窗口大小改变的时候,来动态改变页面元素的大小,可以采用window的resize事件,实现代码:
<script type="text/javascript">
var n = 0;
function resizehandler(){
console.log(new Date().getTime());
console.log(++n);
} window.onresize = resizehandler;
</script>
功能能够实现,都是当我们用拖拽的方式改变浏览器大小的时候,控制台会不断打印执行resizehandler的函数的结果。
一次简单的拖拽会让resizehandler()函数执行很多次,实际在显示项目中resizehandler函数可能会很复杂,甚至会涉及到前后端的数据交互,所以一次拖拽执行很多次很明显是不能够接受的。
函数去抖
其实我们的本意只是窗口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">
var 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>
这样的话执行就没有问题了。
函数防抖的另一种方法
预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个周期。
function throttle(method, dalay){
var timer = null;
return function(){
var context = this, args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
method.apply(context, args);
}, delay);
}
}
调用一下试试,一样的效果
<script type="text/javascript">
var 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>
比较
两种方法都是利用了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);
这样,既没有频繁执行也没有就最后执行。
总结
对于函数节流在做动态响应用户行为方面有较大的使用频率,具体使用基础版本的函数节流还是改动版本的还要根据业务场景进行具体分析。
throttle和debounce均是通过减少实际逻辑处理过程的执行来提高事件处理函数运行性能的手段,并没有实质上减少事件的触发次数。 (逃)

JavaScript函数节流(throttle)与函数去抖(debounce)的更多相关文章
- [JavaScript] 函数节流(throttle)和函数防抖(debounce)
js 的函数节流(throttle)和函数防抖(debounce)概述 函数防抖(debounce) 一个事件频繁触发,但是我们不想让他触发的这么频繁,于是我们就设置一个定时器让这个事件在 xxx 秒 ...
- javascript 函数节流 throttle 解决函数被频繁调用、浏览器卡顿的问题
* 使用setTimeout index.html <html> <head> <meta charset="UTF-8"> <title ...
- js 函数节流throttle 函数去抖debounce
1.函数节流throttle 通俗解释: 假设你正在乘电梯上楼,当电梯门关闭之前发现有人也要乘电梯,礼貌起见,你会按下开门开关,然后等他进电梯: 但是,你是个没耐心的人,你最多只会等待电梯停留一分钟: ...
- JS中的函数节流throttle详解和优化
JS中的函数节流throttle详解和优化在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(mousemove),这种事件有一个特点,在一个正常的操作中,有可能在一个短的 ...
- 函数节流throttle和防抖debounce
throttle 函数节流 不论触发函数多少次,函数只在设定条件到达时调用第一次函数设定,函数节流 1234567891011 let throttle = function(fn,intervalT ...
- js 高程 函数节流 throttle() 分析与优化
在 js 高程 22.3.3章节 里看到了 函数节流 的概念,觉得给出的代码可以优化,并且概念理解可以清晰些,所以总结如下: 先看 函数节流 的定义,书上原话(斜体表示): 产生原因/适用场景: 浏览 ...
- 微信小程序:防止多次点击跳转(函数节流)
场景 在使用小程序的时候会出现这样一种情况:当网络条件差或卡顿的情况下,使用者会认为点击无效而进行多次点击,最后出现多次跳转页面的情况,就像下图(快速点击了两次): 解决办法 然后从 轻松理解JS函数 ...
- 【Javascript函数】节流throttle和间隔控制dbounce
一.throttle 函数节流,指把很小时间内触发的N多事件,节流成1个事件. 我们这里说的throttle就是函数节流的意思.再说的通俗一点就是函数调用的频度控制器,是连续执行时间间隔控制.主要应用 ...
- 深入理解javascript函数进阶系列第三篇——函数节流和函数防抖
前面的话 javascript中的函数大多数情况下都是由用户主动调用触发的,除非是函数本身的实现不合理,否则一般不会遇到跟性能相关的问题.但在一些少数情况下,函数的触发不是由用户直接控制的.在这些场景 ...
- JS的函数节流(throttle)
什么是函数节流? 介绍前,先说下背景.在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(其核心就是绑定mousemove),这种事件有一个特点,就是用户不必特地捣乱,他在 ...
随机推荐
- PHP:判断客户端是否使用代理服务器及其匿名级别
要判断客户端是否使用代理服务器,可以从客户端所发送的环境变量信息来判断. 具体来说,就是看HTTP_VIA字段,如果这个字段设置了,说明客户端使用了代理服务器. 匿名级别可以参考下表来判断. 给出一个 ...
- StreamSets学习系列之StreamSets是什么?
不多说,直接上干货! StreamSets是一个侧重数据集成.数据加工流程构建的平台,也是一个开源的产品.通过StreamSets,用户可以方便的接入不同的数据源,并且完成数据加工流程的构建.Stea ...
- 如何用R来处理数据表的长宽转换(图文详解)
不多说,直接上干货! 很多地方都需用到这个知识点,比如Tableau里. 通常可以采取如python 和 r来作为数据处理的前期. Tableau学习系列之Tableau如何通过数据透视表方式读取 ...
- FineBI学习系列之FineBI的Windows里安装步骤(图文详解)
不多说,直接上干货! 先进入FineBI官网. http://www.finebi.com/product/download/ windows系统里FineBI的安装流程 1.从FineBI官网下载 ...
- GO入门——2. 变量
1 基本类型 零值并不等于空值,而是当变量被声明为某种类型后的默认值, 通常情况下值类型的默认值为0,bool为false,string为空字符串,引用为nil. 1.1 布尔类型 关键字:bool ...
- CCF 201509-3 模版生成系统
试题编号: 201509-3 试题名称: 模板生成系统 时间限制: 1.0s 内存限制: 256.0MB 问题描述 成成最近在搭建一个网站,其中一些页面的部分内容来自数据库中不同的数据记录,但是页面的 ...
- Redis3.2.4 Cluster集群搭建
服务器环境:192.168.1.105192.168.1.160每台服务器搭建3个节点,组成3个主节点,3个从节点的redis集群. 注意:防火墙一定要开放监听的redis端口,否则会创建失败. 一. ...
- Ajax初始接触
演示JS对象的属性,方法和事件的使用 (1)window.location.href (2)form.submit() <form action="" method=&quo ...
- js拦截全局ajax请求
你是否有过下面的需求:需要给所有ajax请求添加统一签名.需要统计某个接口被请求的次数.需要限制http请求的方法必须为get或post.需要分析别人网络协议等等,那么如何做?想想,如果能够拦截所有a ...
- new Thread与线程创建
概要:new Thread 并不意味着已经创建了一个线程,只能说明创建一个类的对象实例而已.而真正创建线程的是start()方法,此方法将调用本地方法start0()创建本地线程,而Thread的ru ...