javaScript性能优化:防抖和节流由浅入深的小实例

防抖和节流由浅入深的小实例

网上关于防抖和节流的文章五花八门,

有些人还把防抖和节流的概念搞混了,

有些人写的代码只提出概念,

没有实际应用的实例,

这导致大家看完了,也理解了概念原理,但是实际应用中,把它封装成为函数,并在多事件调用的时候就不会做了。

我写了一些小小的实例,大家可以把代码粘贴到本地,实际测试一下,

既能明白防抖和节流两个问题的区别,也能实际应用在事件中。

html code:

<body style="padding-top:50px;">
    <nav class="navbar fixed-top navbar-expand-lg navbar-light " id="nav6" >
        <div class="container">
            <a class="navbar-brand" href="#">防抖与节流</a>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor03" aria-controls="navbarColor03" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarColor03">
                <ul class="navbar-nav mr-auto">
                <li class="nav-item active">
                    <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">Features</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">Pricing</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">About</a>
                </li>
                </ul>
                <form class="form-inline my-2 my-lg-0">
                <input class="form-control mr-sm-2" type="text" placeholder="Search">
                <button class="btn btn-secondary my-2 my-sm-0" type="submit">Search</button>
                </form>
            </div>
        </div>
    </nav>
    <div class="container" style="height:3000px;">
        <div class="row mt-5">
            <div class="col">
                <div class="alert alert-dismissible alert-primary">
                    <button type="button" class="btn btn-warning" id="btn1">点击增加</button>
                    <strong id="sum1">00</strong> 节流前
                </div>
            </div>
            <div class="col">
                <div class="alert alert-dismissible alert-primary">
                    <button type="button" class="btn btn-warning" id="btn2">点击增加</button>
                    <strong id="sum2">00</strong> 使用if节流后
                </div>
            </div>
            <div class="col">
                    <div class="alert alert-dismissible alert-primary">
                        <button type="button" class="btn btn-warning" id="btn3">点击增加</button>
                        <strong id="sum3">00</strong> 使用setTimeout防抖
                    </div>
                </div>
        </div>
        <div class="row">
                <div class="col">
                    <div class="alert alert-dismissible alert-primary">
                        <button type="button" class="btn btn-warning" id="btn4">点击增加</button>
                        <strong id="sum4">00</strong> 节流加防抖
                    </div>
                </div>
                <div class="col">
                    <div class="alert alert-dismissible alert-primary">
                        <div class="form-group">
                            <label class="col-form-label " for="input5">在input上使用防抖</label>
                            <input type="text" class="form-control" placeholder="请输入内容" id="input5">
                        </div>
                        <p >在input上使用防抖</p>
                        <ul class="list-group list-group-flush" id="text5">
                        </ul>
                        
                    </div>
                </div>
                <div class="col">
                        <div class="alert alert-dismissible alert-primary">
                            <button type="button" class="btn btn-warning" id="btn6">点击增加</button>
                            <strong id="sum6">00</strong> 备用
                        </div>
                    </div>
            </div>
    </div>
</body>

css:

<link rel="stylesheet" type="text/css" href="https://bootswatch.com/4/solar/bootstrap.min.css" />

js code:

节流前

var sum1 = document.getElementById('sum1');
var btn1 = document.getElementById('btn1');
btn1.onclick = function (){
    sum1.innerText = parseInt(sum1.innerText)+ 1;
}

这个时候,你点击按钮就发现,点的越快,数值增加的越快。

性能优化:降低代码执行频率

使用if节流后

var sum2 = document.getElementById('sum2');
var btn2 = document.getElementById('btn2');
function throttle2 (fn,t){
var lastTime = 0;
return function(e){
    var nowTime = new Date().getTime();
    if(nowTime - lastTime > t){
fn.apply(this, arguments);
lastTime = nowTime;
    }
}
}
function click2 (e){
    //console.log(this, e);
    sum2.innerText = parseInt(sum2.innerText) + 1;
}
btn2.onclick = throttle2(click2,1000);

添加节流后,你点击按钮再快,数值还是按照1000一个的速度增加的。

我已经将节流操作,封装为一个函数,只需调用这个函数,就能给你需要添加的事件,添加上节流功能。

使用setTimeout防抖

var sum3 = document.getElementById('sum3');
var btn3 = document.getElementById('btn3');
function debounce3(fn,t){
var timer = null;
return function(){
    var context = this, args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function(){
        fn.apply(context,args);
    }, t);
 }
}
function click3 (e){
    console.log(this, e);
    sum3.innerText = parseInt(sum3.innerText) + 1;
}
btn3.onclick = debounce3(click3,1000);

同样的事件,使用防抖,你会发现,和节流不同的是,你每次快速点击的过程中,是不计算时间的,只有你停止点击按钮,才开始计时,

这里我定的时间是1000毫秒,你可以方便的在调用事件的时候修改时间。

我们还可以把防抖和节流一起使用,

防抖+节流,使用if+setTimeout

var sum4 = document.getElementById('sum4');
var btn4 = document.getElementById('btn4');
function throttle4(fn,n,t){
var timer = null, begin = new Date();
return function(){
    var context = this, args = arguments,current = new Date();
    clearTimeout(timer);
    if (current-begin>=n) {
        fn.apply(context,args);
        begin = current;
    } else {
        timer = setTimeout(function(){
            fn.apply(context,args);
        }, t);
    }
    
 }
}
function click4 (e){
    console.log(this, e);
    sum4.innerText = parseInt(sum4.innerText) + 1;
}
btn4.onclick = throttle4(click4,1000,500);

我把上面的事件都写成一个类型--按钮点击,方便大家比较差异。

下面是防抖的其他应用。

在input输入框上使用setTimeout防抖

var text5 = document.getElementById('text5');
var input5 = document.getElementById('input5');
function debounce5(fn,t){
var timer = null;
return function(){
    var context = this, args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function(){
        fn.apply(context,args);
    }, t);
 }
}
function ajax5 (e){
    //console.log(this, e);
    var oLi = document.createElement('li');
    oLi.setAttribute('class', 'list-group-item');
    oLi.innerText = input5.value;
    text5.appendChild(oLi);
    //text5.innerText = input5.value;
}
input5.oninput = debounce3(ajax5,1000);

这个在百度搜索上很常用,当你输入一些词语的时候,不会每时每刻,每个字都发送到服务器,去请求数据,只有你输入停顿之后,才显示搜索结果。

以上,都是大白话的说法,下面用比较严谨的说法总结一下:

总结:防抖的原理:

通过setTimeout设置毫秒时间,在你触发事件后,n秒内没有再次触发事件,处理函数才会执行,如果在这一段时间来到之前,又一次触发了事件,那就重新计时。

用户停止输入的时候,才触发查询的请求。

下面是节流的其他应用

把函数节流,应用在滚动事件onscroll上

这个实例,实现了顶部导航条滚动变色的功能。

var body = document.getElementsByTagName('body')[0];
var oNav = document.getElementById('nav6');
function changeColor(){
    //console.log("看看调用了几次?");
    var t = document.documentElement.scrollTop || document.body.scrollTop;
    var classVal;
        if (t > 200) {
           oNav.style.backgroundColor = "#B58900";
        } else {
           oNav.style.backgroundColor = "#FDF6E3";
        }  
}
body.onscroll = throttle2(changeColor,1000);

使用节流前,你每滚动一下都发出大量的请求,

使用节流后,你不停地滚动页面结束之后,才发出请求。

总结:

节流保证了一段时间内,核心代码只执行一次

每间隔某个时间去执行某函数,避免函数的过多执行

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

推荐阅读更多精彩内容

  • 最近在研究页面渲染及web动画的性能问题,以及拜读《CSS SECRET》【https://github.com/...
    qyer0222阅读 2,283评论 0 6
  • 最近在研究页面渲染及web动画的性能问题,以及拜读《CSS SECRET》(CSS揭秘)这本大作。 本文主要想谈谈...
    108N8阅读 1,088评论 0 11
  • 前言 最近和前端的小伙伴们,在讨论面试题的时候。谈到了函数防抖和函数节流的应用场景和原理。于是,想深入研究一下两者...
    youthcity阅读 23,520评论 5 78
  • 函数节流 还记得上篇文章中说到的图片懒加载吗?我们在文章的最后实现了一个页面滚动时按需加载图片的方式,即在触发滚动...
    柏丘君阅读 2,840评论 1 19
  • 昨晚的老公有点微醉,从不在家长群发言的他说了好多,有点开心也有点担心。开心的是他可以关注孩子的学习成长,担心的是他...
    嘟嘟世界阅读 266评论 0 0