函数的防抖和节流

定义

在JS里,有一些事件是很容易频繁触发的,比如窗口的resize、scroll、鼠标的onmousemove等操作,在事件频繁触发的过程中,不可避免的导致频繁执行触发事件中的函数。为了防止这种情况的发生,主流的解决方案有两种,防抖(debounce)和节流(throttle)

频繁执行情况

            var num = 1;
            var moveCntent = document.getElementById('example')
            function count(){
                moveCntent.innerHTML++;
            }
            moveCntent.onmousemove = count

效果如下:

image.png

可以明显的看到,count 函数执行的非常频繁,假如现在我们count函数里执行的是一个Ajax请求,那么问题就会非常严重了。

防抖

函数防抖就是在一段时间(n毫秒)触发或调用函数时,只执行一次; 也可以理解为触发n毫秒之后才会调用一次。

防抖函数的写法主要有两种,非立即执行版本立即执行版本

非立即执行版

                var num = 1;
                var moveCntent = document.getElementById('example')
                function count(){
                        moveCntent.innerHTML++;
                }
                moveCntent .onmousemove = count
                function debounce(fn,delay){
                        var timer;
                        return function(){
                            var _this = this;
                            var args = arguments;
                            if(timer) clearTimeout(timeout);
                            timer = setTimeout(function(){
                                fn.apply(_this,args)
                            },delay)
                            }
                    }
                moveCntent.onmousemove = debounce(count,1000)

原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。

效果如下:

image

在触发事件1秒后才执行,如果在触发事件的一秒内又触发了事件,则重新计算函数执行时间

立即执行版

                function debounce(fn,delay){
                    var timer;
                    return function(){
                        var _this = this;
                        var args = arguments;
                        if(timer){
                            clearTimeout(timer);
                        } 
                        if(!timer){
                            fn.apply(_this,args);
                        } 
                        timer = setTimeout(function(){
                            timer = null;
                        },delay);
                    };
                }

立即执行版本和非例行版本的区别是:

  • 立即执行版本:触发事件后函数立即执行,然后n秒内不触发时间才会继续执行
  • 非立即执行版本:触发事件后函数不会立即执行,而是在n秒回才会执行

节流

函数节流,就是指连续触发的事件在n秒钟只执行一次函数。降低函数的执行频率,对于函数节流,通常也也有两种方式实现,分别是时间戳版定时器版

时间戳版

                function throttle(fn,delay){
                    var previous = 0;
                    return function(){
                        var now = Date.now();
                        var _this = this;
                        var args = arguments;
                        if(now - previous > delay){
                            fn.apply(_this,args);
                            previous = now;
                        }
                    };
                }
                moveCntent.onmousemove = throttle(count,1000)

当高频事件触发时,第一次会立即执行,而后再怎么频繁地触发事件,也都是每delay时间才执行一次。

效果如下:

image

持续触发事件的过程中,函数会立即执行,并且每一秒执行一次

定时器版

                function throttle(fn,delay){
                    var timer;
                    return function(){
                        var _this = this;
                        var args = arguments;
                        if(!timer){
                            timer = setTimeout(function(){
                                timer = null;
                                fn.apply(_this,args);
                            },delay);
                        }
                    };
                }

在持续触发事件的过程中,函数不会立即执行,并且每一秒执行一次,停止触发事件后,还会再执行一次

效果如下:

image

时间戳版本和定时器版本的区别是:

  • 时间戳版本:触发事件后函数立即执行,每n秒执行一次
  • 定时器版本:触发事件后函数不会立即执行,每n秒执行一次,停止触发后还会执行一次

总结

函数防抖:将几次操作合并为一此操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。

函数节流:使得一定时间内只触发一次函数。原理是通过判断是否到达一定时间来触发函数。

区别: 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。

转自 https://www.jianshu.com/p/35e6ed1642e4

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335