资讯专栏INFORMATION COLUMN

JavaScript中函数节流的理解

taohonghui / 1979人阅读

摘要:每次鼠标移动都是这样的处理过程,直到鼠标不再移动一秒钟后,定时器中的函数才被使用。

函数节流的原理

函数节流,就是对会频繁触发的函数事件做一些限制,让这些函数可以在每隔一定的时间或者每次满足一定的条件下再触发。一般我们会给他起一个名字throttle。也就是节流的意思。一般这样的函数有 resize事件、ontouchmove事件等。

举个简单的例子




    
    测试函数节流
    



    

上面的代码就是简单的渲染出来一个div 然后给这个div绑定了一个鼠标移动事件。但是我们在实际情况下,这种体验是不好的,因为这个事件会被十分频繁的触发。只要我们在这个div上移动鼠标就会弹出这个阻塞性的事件alert,所以我们希望每隔一定时间提醒一下“您的鼠标正在移动”。
下面写一个节流的函数throttle()

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

然后我们修改一下页面上的代码:




    
    测试函数节流
    



    

下面我仔细解释一下这个节流函数。

函数利用闭包的形式存储了一个timer定时器变量,说实话我刚开始看别人在写这个节流函数的时候,也是不太容易懂,只是马马虎虎觉得是这样的,直到我亲自实现一遍,才明白。在这里建议亲自动手,丰衣足食~~

这个timer变量当然也可以写在全局作用域中,但是可能会跟全局作用域中的变量产生冲突,所以在这里用闭包的形式来提供,防止它污染全局作用域。(看好多人在这里用“污染”,我想可能是如果有很多像timer这样的变量都放在全局作用域中,到时候肯定容易与在全局作用域中常用的变量混淆。因为它毕竟只是在这个节流函数做定时器使用)。

然后就是throttle函数返回的函数了。在这个函数中,要保存好传进来的执行上下文this,和参数arguments。应为我们要注意的是setTimeout()函数中作用域是全局的,也就是setTimeout中的this指的是window在这里这个执行上下文其实就是container对象,传入的参数就是鼠标移动这个事件的所有信息我们将这个container这个对象的鼠标移动事件函数重写成alertSomething这个函数。同时鼠标移动事件的信息也作为参数传入进去这一点也是我打印出他的相应信息后才恍然大悟,可能平时我们会理所当然的知道就是这样子的,但是为什么会这样子呢,我们知道了alertSomething这个函数的参数和执行上下文是怎么传进去的,那直接调用elementobj.onmousemove=function(){xxxxxx}这个函数的时候,上下文和参数是怎么传入进去的也应该是这样的原理吧。这是我的个人理解。

明白了上面的基本原理,我们再梳理一下节流函数发挥作用的过程:第一次调用这个节流函数的时候也就是第一次触发鼠标移动事件的时候,timer是没有的,所以clearTimeout(timer)清理的定时器也是没有的,但是等第二次触发鼠标移动事件的时候,鼠标移动事件的处理函数就是一直是throttle返回的函数了。首先会清理掉上次调用的时候的定时器,然后重新设置一个定时器。每次鼠标移动都是这样的处理过程,直到鼠标不再移动一秒钟后,定时器中的函数才被使用。

总之仔仔细细理解一下这个过程感觉真好!

但是如果我们需要自定义延迟的事件的话怎么办呢,下面我们可以再改进一下:

function throttle(func,delay){
    var timer;
    return function(){
        var context = this;
        var args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function(){
            func.apply(context,args);
        },delay);
    }
    
}
function dealMouseMove(){
    alert("您的鼠标正在移动");
};
document.getElementById("container").onmousemove = throttle(dealMouseMove,500);
在这里感谢 Toobugflowmemo 两位大神的指正,上面函数的功能更应该称之为debounce,也即是消除抖动的意思。前端技术中常用的throttle相当于一个频率控制器,让一段时间内快速触发很多次的事件处理程序可以只触发一定的次数, 而debounce不只是减少了触发次数,而且要满足一定的条件下才会触发。两者实现方法都是差不多的,叫法不一样而已,不能将两者割裂开来。

可以参考的相关网址:http://www.css88.com/archives/4648
可以参考的相关网址:http://www.alloyteam.com/2012/11/javascript-throttle/

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79000.html

相关文章

  • JavaScript 节流函数 throttle 详解

    摘要:后续的一些辅助性优化读者可以自己琢磨,如函数指向,返回值保存等。 原文:https://keelii.github.io/2016/06/11/javascript-throttle/ 在浏览器 DOM 事件里面,有一些事件会随着用户的操作不间断触发。比如:重新调整浏览器窗口大小(resize),浏览器页面滚动(scroll),鼠标移动(mousemove)。也就是说用户在触发这些浏览...

    instein 评论0 收藏0
  • JavaScript专题系列20篇正式完结!

    摘要:写在前面专题系列是我写的第二个系列,第一个系列是深入系列。专题系列自月日发布第一篇文章,到月日发布最后一篇,感谢各位朋友的收藏点赞,鼓励指正。 写在前面 JavaScript 专题系列是我写的第二个系列,第一个系列是 JavaScript 深入系列。 JavaScript 专题系列共计 20 篇,主要研究日常开发中一些功能点的实现,比如防抖、节流、去重、类型判断、拷贝、最值、扁平、柯里...

    sixleaves 评论0 收藏0
  • 前端进击巨人(八):浅谈函数防抖与节流

    摘要:隆重请出主角防抖与节流。防抖与节流的异同相同都是防止某一时间段内,函数被频繁调用执行,通过时间频率控制,减少回调函数执行次数,来实现相关性能优化。参考文章分钟理解的节流防抖及使用场景函数防抖和节流 showImg(https://segmentfault.com/img/bVburM8?w=800&h=600); 本篇课题,或许早已是烂大街的解读文章。不过春招系列面试下来,不少伙伴们还...

    _Zhao 评论0 收藏0
  • 理解节流与防抖

    摘要:节流节流限制了一个函数可以在短时间内被调用的次数。更新防抖防抖确保了一个函数只有在一个固定时间段内没有被调用过后,才会再次被调用。再换句话说防抖会等待事件不再高频发生,再触发。这个网站很好的可视化了节流与防抖。 节流 Throttling 节流限制了一个函数可以在短时间内被调用的次数。可以这样形容:在一毫秒内最多执行此函数 1 次。 Throttling enforces a maxi...

    glumes 评论0 收藏0

发表评论

0条评论

taohonghui

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<