setTimeout 与函数节流与防抖

setTimeout简介

Javascript是单线程语言,不过允许通过设置超时调用(setTimeout)和间歇调用(setInterval)来调度代码在特定时刻执行。这两个方法都属于window对象,接受两个参数:第一个参数是要执行的代码(一般为函数),第二个是执行代码前需要等待的时间(ms)。

setTimeout :第二个参数,即表示需要等待的时间,但经过该时间后指定的代码不一定会立即执行。因为JS是单线程的,为了控制要执行的代码,就有一个JS任务队列,这些任务会按照它们被添加到队列中的顺序去执行。而setTimeout的第二个参数就是指定经过多长时间将第一个参数指定的任务添加到队列中。如果任务队列是空的,那么新添加的任务会立即执行;否则它就要等前面的任务执行完了以后才能开始执行。

  // 休眠函数
   let sleep=function(n){
       let start=new Date().getTime();
       while(true){
           if(new Date().getTime()-start>n){
               break;
           }
       }
       console.log('wake up.')
   }

   // 超时调用
    var globalAttribute='global';
    let tmId=setTimeout(()=>console.log(this.globalAttribute),2500);
    for(let i=0;i<5;i++){
        setTimeout(()=>console.log(i),1000);
        sleep(1000);
    }

chrome中结果

注意for语句中使用了let声明i(ES6语法),不同于通过var声明。所以i的值不是for语句结束时的值。
从以上例子可以看出,两个setTimeout都没有按设定的时间执行,因为任务队列中有for循环这个任务(里面的sleep函数比较耗时)仍在执行,只有等它执行完毕,才会执行超时调用中设置的任务。
setInterval :与setTimeout 类似,只是会每隔一段时间就会执行,在不受干涉的情况下会一直执行,所以要使用clearInterval取消。

介绍完setTimeout ,下面才是重头戏。
函数节流:高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。(例如一直拖动进度条,如果与scroll绑定的代码不加控制,那只要拖动,相应代码就会高频执行;使用节流后,可以设置为特定时间(如500ms)才执行一次scroll事件处理代码)。
函数防抖:频繁触发的情况下,只有停下来一段事件,才执行一次相应代码。(搜索引擎的联想查询功能,它是在用户进行键入的时候监听keypress事件,然后异步去查询结果。如果用户快速的输入了一连串的字符,假设是10个字符,那么就会在短时间内触发了10次的请求,这无疑不是我们想要的。我们想要的是用户停止输入过了一会(很短,可以设定),才去触发查询的请求 )
区别:防抖和节流本质是不一样的。防抖是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。

    function throttle(fn) {
        let canRun = true; // 通过闭包保存一个标记
        return function () {
            if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return
            canRun = false; // 立即设置为false
            setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
                fn.apply(this, arguments);
                // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
                canRun = true;
            }, 500);
        };
    }
    function sayHi(e) {
        console.log(e.target.innerWidth, e.target.innerHeight);
    }
    window.addEventListener('resize', throttle(sayHi));

函数节流示意代码

函数防抖
   function debounce(fn) {
      let timeout = null; // 创建一个标记用来存放定时器的返回值
      return function () {
        clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
        timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
          fn.apply(this, arguments);
        }, 500);
      };
    }
    function sayThis() {
      console.log(this);
    }

    var inputEle = document.getElementById('inp');// <input type="text" id="input">
    inputEle.addEventListener('input', debounce(sayThis)); // <input type="text" id="input">

Note:这里面关于this其实有些细节,首先要知道:(1)箭头函数自己没有this,如果箭头函数被非箭头函数包含,this 绑定的就是最近一层非箭头函数的 this。(2)使用ele.addEventListener( 'specificEvent', eventHandler)给 ele 设置事件监听时,传入 eventHandlerthis指的就是 ele.
那么inputEle.addEventListener('input', debounce(sayThis)),给输入元素上的input监听时,设置的处理函数为 debounce(sayThis) 执行返回的匿名函数,该函数中的 this 指向的就是 输入元素,进而可以确定该函数中的箭头函数内的 this。

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