浅谈JavaScript函数节流


Posted in Javascript onDecember 09, 2014

浏览器中某些计算和处理要比其他的昂贵的多。例如,DOM操作比起非DOM交互需要更多的内存和CPU时间。连续尝试进行过多的DOM相关操作可能会导致 浏览器挂起,有时候甚至会崩溃。尤其在IE中使用onresize事件处理程序的时候容易发生,当调整浏览器大小的时候,该事件连续触发。在 onresize事件处理程序内部如果尝试进行DOM操作,其高频率的更改可能会让浏览器崩溃。

     函数节流背后的基本思想是,某些代码不可以在没有间断的情况连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用 该函数时,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其 替换为一个新的定时器。目的是只有在执行函数的请求停止了一段时间之后才执行。

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

应用举例:
     假设有一个<div/>元素需要保持它的高度始终等同于宽度,可作如下编码:

function resizeDiv(){
        var div = document.getElementById("mydiv");
        div.style.height = div.offsetWidth + "px";
      }
      window.onresize = function(){
        throttle(resizeDiv);
      }

这里,调整大小的功能被放入了一个叫做resizeDiv的单独函数中,然后onresize事件处理程序调用throttle()并传入 resizeDiv函数,而不是直接调用resizeDiv()。多数情况下,用户是感觉不到变化的,虽然给浏览器节省的计算可能非常大。

下面是其他网友的补充

今天主要写写我们平时工作中需要的函数节流。可能有的朋友对函数节流没有意识。其实,在工作中,很多场景都需要我们进行js的节流。最常见的是屏幕伸缩resize,以及touchmove或者scroll等事件的时候。大家不知道有没有看我之前写的文章!jquery判断页面滚动条上滚下滚,touchmove的滑动方向,大家在使用这些例子的时候,会发现页面不停的触发touchmove或者scroll因为这里没有关系到页面的重绘,因此,我在这里没有使用javascript函数节流。但是,当我们使用window.onresize的时候,也会不停的触发resize事件!这里就会关系到页面的重新绘制问题了。因此,在window的resize的时候,我们推荐大家使用函数节流的方式!

javascript函数节流简介
假如你对我上面一大坨文字感到头大,没关系,我在这里简单举例说明一下函数节流吧!例如当我们使用

$(window).resize(function(){
      console.log("haorooms window resize");
    })

会发现:

浅谈JavaScript函数节流

这里会输出好多次。我们简单的缩小一下窗口,就会不停的触发!

这样在div很多的时候,页面不停重绘,要是遇到版本比较低的IE等,很可能会出现浏览器崩溃的现象!为了避免这种情况,我们可以用函数节流的方式。基本的思想是:第一次调用函数的时候,我们创建一个定时器,在指定时间间隔之后运行代码,第二次调用的时候,会清楚前一个定时器,并重新设置一个。如果前一个定时器已经执行过了,那么这个操作就没有有意了,如果定时器尚未执行,就会将其替换为一个新的定时器。目的是在执行函数停止了一段时间之后再执行。

用对象的方式可以如下写:

var haoroomstest={
      timeoutId:null,
      performProcessing:function(){        
          console.log("resize");      

      },
      process:function(){
        clearTimeout(this.timeoutId);
        var that=this;
        this.timeoutId=setTimeout(function(){
          that.performProcessing();
        },500)
      }
    }

这样之后,我们再用:

$(window).resize(function(){ haoroomstest.process(); })

浅谈JavaScript函数节流

这样就会减少请求,减少dom重绘,达到节流的目的!

函数节流其他方式
除了我们运用对象的方式,网上及资料中也介绍了关于函数节流的其他方法和方式,我下面简单介绍几种!

函数方式一

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

我们如下使用

function resizeDIv(){
      console.log("haorooms")
    }

    $(window).resize(function(){
      throttle(resizeDIv)
    })

和上面对象实现了同样的效果!

函数方式二

网上还有一种比较流行的节流方式,我在这里写一下!

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

然后可以这么写:

function resizeDIv(){
      console.log("haorooms")
    }

   window.onresize=throttle(resizeDIv,500);

新需求

我们在做模糊搜索智能联想提示的时候,会在input上面绑定keyup事件。但是我又不想触发的那么频繁,用上面的方式就会有问题。因此,在上面的函数基础上稍加改动,如下:

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);
        }
      }
}

这样触发就不会有之前那么频繁了!

Javascript 相关文章推荐
List all the Databases on a SQL Server
Jun 21 Javascript
“不能执行已释放的Script代码”错误的原因及解决办法
Sep 09 Javascript
UserData用法总结 lanyu出品
Jul 01 Javascript
读jQuery之五(取DOM元素)
Jun 20 Javascript
JQuery基础语法小结
Feb 27 Javascript
Javascript将JSON日期格式化
Aug 23 Javascript
常用原生js自定义函数总结
Nov 20 Javascript
如何使用vuejs实现更好的Form validation?
Apr 07 Javascript
JavaScript 格式化数字、金额、千分位、保留几位小数、舍入舍去
Jul 23 Javascript
详解vue中$nextTick和$forceUpdate的用法
Dec 11 Javascript
详解vue路由
Aug 05 Javascript
详解Typescript里的This的使用方法
Jan 08 Javascript
node.js中的console.log方法使用说明
Dec 09 #Javascript
node.js中的console.warn方法使用说明
Dec 09 #Javascript
node.js中的console.info方法使用说明
Dec 09 #Javascript
浅谈JavaScript实现面向对象中的类
Dec 09 #Javascript
node.js中的console.trace方法使用说明
Dec 09 #Javascript
node.js中的console.time方法使用说明
Dec 09 #Javascript
node.js中的console.timeEnd方法使用说明
Dec 09 #Javascript
You might like
php+xml结合Ajax实现点赞功能完整实例
2015/01/30 PHP
使用新浪微博API的OAuth认证发布微博实例
2015/03/27 PHP
jQuery EasyUI 中文API Layout(Tabs)
2010/04/27 Javascript
推荐40款强大的 jQuery 导航插件和教程(上篇)
2012/09/14 Javascript
Javascript 浮点运算精度问题分析与解决
2014/03/26 Javascript
浅谈jQuery中 wrap() wrapAll() 与 wrapInner()的差异
2014/11/12 Javascript
node.js操作mysql(增删改查)
2015/07/24 Javascript
百度地图api如何使用
2015/08/03 Javascript
基于touch.js手势库+zepto.js插件开发图片查看器(滑动、缩放、双击缩放)
2016/11/17 Javascript
原生javascript实现图片放大镜效果
2017/01/18 Javascript
nodejs 搭建简易服务器的图文教程(推荐)
2017/07/18 NodeJs
js编写简单的聊天室功能
2017/08/17 Javascript
结合mint-ui移动端下拉加载实践方法总结
2017/11/08 Javascript
实例详解带参数的 npm script
2019/05/28 Javascript
小程序分享链接onShareAppMessage的具体用法
2020/05/22 Javascript
JavaScript 中的执行上下文和执行栈实例讲解
2021/02/25 Javascript
[01:29:46]DOTA2上海特级锦标赛C组资格赛#1 OG VS LGD第二局
2016/02/27 DOTA
[56:18]DOTA2上海特级锦标赛主赛事日 - 4 败者组第四轮#2 MVP.Phx VS Fnatic第二局
2016/03/05 DOTA
Python合并多个装饰器小技巧
2015/04/28 Python
python计算方程式根的方法
2015/05/07 Python
Python使用迭代器打印螺旋矩阵的思路及代码示例
2016/07/02 Python
Linux 下 Python 实现按任意键退出的实现方法
2016/09/25 Python
python 动态生成变量名以及动态获取变量的变量名方法
2019/01/20 Python
python cumsum函数的具体使用
2019/07/29 Python
Python实现石头剪刀布游戏
2021/01/20 Python
一文读懂python Scrapy爬虫框架
2021/02/24 Python
携程旅行网:中国领先的在线旅行服务公司
2017/02/17 全球购物
纪伊国屋泰国网上书店:Kinokuniya泰国
2017/12/24 全球购物
Senreve官网:美国旧金山的奢侈手袋品牌
2019/03/21 全球购物
小学三年级数学教学反思
2014/01/31 职场文书
先进集体事迹材料
2014/02/17 职场文书
2015庆祝七一建党节94周年活动总结
2015/03/20 职场文书
高一语文教学反思
2016/02/16 职场文书
你喜欢篮球吗?Python实现篮球游戏
2021/06/11 Python
MySQL如何解决幻读问题
2021/08/07 MySQL
python 详解turtle画爱心代码
2022/02/15 Python