这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
这篇文章主要介绍了 JavaScript 函数节流详解及实例的相关资料, 需要的朋友可以参考下
JavaScript 函数节流详解
浏览器一个网页的 UI 线程只有一个,他同时会处理界面的渲染和页面 JavaScript 代码的执行(简单扩展一下,浏览器或者 JavaScript 运行大环境并不是单线程,诸如 ajax 异步回调、hybrid 框架内与 native 通信、事件队列、CSS 运行线程等等都属于多线程环境,不过 ES6 引入了 Promise 类来减少了部分异步情况)。因此当 JavaScript 代码运行计算量很大的方法时,就有可能阻塞 UI 线程,小则导致用户响应卡顿,严重的情况下浏览器会提示页面无响应是否强制关闭。例如网页的页面滚动事件、移动设备的滑动、缩放事件等。即使没有出现严重的性能问题,我们也应该站在性能优化的角度将短时间内会多次触发的大规模处理时间进行分流计算。
如何有效避免 UI 线程运行过长的代码,是所有用户交互应用需要考虑的问题,同样的问题在客户端 Android 可以使用 UI 主线程开子线程来分散计算。与此对应的,js 也可以通过引入 webWorker 来分散计算,但是在 js 中有一个更简单并且效果不错的方法:函数节流。使用函数节流的核心技巧就是使用定时器分段计算。具体的实现方式大致有两种思路。
· 方法一
1. 这种实现方式的思路很好理解:设置一个一间隔时间,比如 50 毫秒,以此时间为基准设置定时器,当第一次触发事件到第二次触发事件间隔小于 50 毫秒时,清除这个定时器,并设置一个新的定时器,以此类推,直到有一次事件触发后 50 毫秒内没有重复触发。代码如下:
- function debounce(method){
- clearTimeout(method.timer);
- method.timer=setTimeout(function(){
- method();
- },50);
- }
这种设计方式有一个问题:本来应该多次触发的事件,可能最终只会发生一次。具体来说,一个循序渐进的滚动事件,如果用户滚动太快速,或者程序设置的函数节流间隔时间太长,那么最终滚动事件会呈现为一个很突然的跳跃事件,中间过程都被节流截掉了。这个例子举的有点夸张了,不过使用这种方式进行节流最终是会明显感受到程序比不节流的时候 "更突兀",这对于用户体验是很差的。有一种弥补这种缺陷的设计思路。
· 方法二
2. 第二种实现方式的思路与第一种稍有差别:设置一个间隔时间,比如 50 毫秒,以此时间为基准稳定分隔事件触发情况,也就是说 100 毫秒内连续触发多次事件,也只会按照 50 毫秒一次稳定分隔执行。代码如下:
- var oldTime=new Date().getTime();
- var delay=50;
- function throttle1(method){
- var curTime=new Date().getTime();
- if(curTime-oldTime>=delay){
- oldTime=curTime;
- method();
- }
- }
相比于第一种方法,第二种方法也许会比第一种方法执行更多次(有时候意味着更多次请求后台,即更多的流量),但是却很好的解决了第一种方法清除中间过程的缺陷。因此在具体场景应根据情况择优决定使用哪种方法。
对于方法二,我们再提供另一种同样功能的写法:
- var timer = undefined,
- delay = 50;
- function throttle2(method) {
- if (timer) {
- return;
- }
- method();
- timer = setTimeout(function() {
- timer = undefined;
- },
- delay);
- }
最后说点个外话,说明一下函数节流的名称问题,大家往往会看到 throttle 和 debounce 两个方法名,throttle 可以译为 "节制,卡住",debounce 可以译为 "防反跳"。在《JavaScript 高级程序设计》中作者介绍了方法一,并且作者使用了 "throttle" 这个函数名。而在《第三方 JavaScript 编程》书中同时出现了方法一和方法二,作者将方法一命名为 "debounce",将方法二命名为 "throttle"。国内在同时介绍两个方法的时候有些文章错误的将方法一命名为 "throttle",而将方法二命名为 "debounce",从英语的角度来说是很不负责任的。因此在这里拨乱反正:方法一适合理解为 "防反跳",应命名为 "debounce";方法二适合理解为 "函数节制",应命名为 "throttle"。
来源: http://www.phperz.com/article/17/0520/327892.html