前端性能優化|什麼是防抖和節流?

防抖與節流、節流與防抖,是否是常常讓你不知道誰是誰。前端

乘電梯,若是有人進入電梯(觸發事件),電梯門會等待 5 秒再關閉,在等待期間若是又有人按電梯進入(在 5 秒內再次觸發該事件),電梯門又要從新等待 5 秒,直到最後一我的進入電梯,電梯門在等待 5 秒後關閉。程序員

這就是咱們生活中碰見的防抖,那節流是什麼呢?瀏覽器

打過遊戲的朋友都知道,遊戲當中技能的使用是有冷卻時間的,就算你不停地按技能,也只能在規定時間內觸發一次,這就是節流。防抖和節流是前端優化常常碰見的知識點,快拿好小板凳和我一塊兒開啓接下來的學習吧!緩存

函數防抖(debounce)

一、原理

當持續觸發事件時,在規定的時間內該事件沒有被再次調用,事件處理函數就會執行一次,若是在規定時間內事件再次被調用,就從新開始計時。微信

二、使用場景

按鈕提交場景:防止屢次提交按鈕,只執行最後提交的一次。app

搜索框的聯想詞:只發送最後一次輸入結果的請求。前端優化

進行窗口的 resize、scroll 事件時: 只計算最後一次結果進行執行。函數

輸入框內容的校驗:只進行最後一次輸入的內容校驗。學習

function debounce(func, wait, immediate) {
  let timer;
  let debounced = function () {
    let _this = this;
    let args = arguments;
    clearTimeout(timer);
    if (immediate) {
      let executeNow = !timer;
      timer = setTimeout(function () {
        timer = null;
      }, wait);
      if (executeNow) {
        func.apply(_this, args);
      }
    } else {
      timer = setTimeout(function () {
        func.apply(_this, args)
      }, wait);
    }
    debounced.cancel = function () {
      clearTimeout(timer);
      timer = null;
    }
  }
  return debounced;
}

三、實現

用 immediate 參數控制函數是否當即執行。若是函數是當即執行的,就當即調用;若是函數是延遲執行的,就緩存上下文和參數,放到延遲函數中去執行。一旦開始一個定時器,只要定時器還在,每次觸發函數都會從新計時。一旦事件不觸發了,定時器時間到,執行一次事件函數,定時器重置爲 null,就能夠再次點擊了。優化

函數節流(throttle)

一、原理

當持續觸發事件時,保證在規定的時間內調用一次事件處理函數。若是這個單位時間內觸發屢次函數,只有一次有效。

二、使用場景

DOM 元素的拖拽功能實現: 一個時間週期去獲取一次位置並計算,防止超高頻次觸發位置變更。
進行窗口的 resize、scorll 事件時: 只計算最後一次結果進行執行。

三、實現

時間戳方式:當觸發事件的時候,咱們取出當前的時間戳,而後減去以前的時間戳,若是大於設置的時間週期,就執行函數,而後更新時間戳爲當前的時間戳;若是小於,就不執行。該方式第一次事件當即執行,最後一次事件不執行。

function throttle(func,wait){
  let _this,args;
  let preTime = 0;
  return function(){
    _this = this;
    args = arguments;
    let now = new Date().valueOf();
    if(now-preTime > wait){
      func.apply(_this,args);
      preTime = now;
    }
  }
}

定時器方式:當觸發事件的時候,咱們設置一個定時器,再觸發事件的時候,若是定時器存在,就不執行,直到定時器執行完,而後執行函數,清空定時器,這樣就能夠設置下個定時器。該方式第一次事件不當即執行,最後一次事件執行。

function throttle(func,wait){
  let _this, args, timer;
  return function(){
    _this = this;
    args = arguments;
    if(!timer){
      timer = setTimeout(() => {
        timer = null;
        func.apply(_this,args);
      },wait);
    }
  }
}

時間戳 + 定時器方式: 用函數參數實現配置項(leading:boolean、trailing:boolean),控制事件第一次是否當即觸發和事件最後一次是否觸發。

function throttle(func,wait,options){
  let _this, args, timer;
  let preTime = 0;
  if(!options) options = {};
  return function(){
    _this = this;
    args = arguments;
    let now = new Date().valueOf();
    if(options.leading === false && !preTime)  {
      preTime = now;
    }
    if((now - preTime) > wait){
      if(timer){
        clearTimeout(timer);
        timer = null;
      }
      func.apply(_this,args);
      preTime = now;
    } else if(!timer && options.trailing !== false){
      timer = setTimeout(() => {
        preTime = new Date().valueOf;
        timer = null;
        func.apply(_this,args);
      },wait);
    }
  }
}

總結

函數防抖:

將幾回操做合併爲一次操做進行。原理是維護一個計時器,規定在 delay 時間後觸發函數,可是在 delay 時間內再次觸發的話,就會取消以前的計時器而從新設置。這樣一來,只有最後一次操做能被觸發。

函數節流:

使得必定時間內只觸發一次函數。原理是經過判斷是否到達必定時間來觸發函數。

二者的區別:

函數節流無論事件觸發有多頻繁,都會保證在規定時間內必定會執行一次事件處理函數,而函數防抖只是在最後一次事件後才觸發一次函數。

做者

青雲科技平臺及服務部 林茂

福利時刻

關注「青雲技術社區」公衆號,添加「青仔」微信 qingcloud-community,加入技術交流羣,就有機會得到價值 139 元《JavaScript 權威指南 (原書第7版)》。

獎品介紹

「犀牛書」已經成爲 JavaScript 程序員心中公認的權威指南。憑着完整的內容、細緻的講解以及海量針對性的示例而受到讀者的一致好評,這本鉅著主要講述的內容涵蓋 JavaScript 語言自己,以及 Web 瀏覽器所實現的 JavaScriptAPI。

在這裏插入圖片描述

抽獎說明

獎品:技術圖書《JavaScript 權威指南 (原書第7版)》 2 本 活動時間:即日起至 2021 年 8 月 11 日 16:00 活動自動開獎後,請於 48 小時內聯繫「青仔」微信 qingcloud-community,留下領獎信息。

相關文章
相關標籤/搜索