JS函數節流(throttle)和函數去抖(debounce)

    看到一篇不錯的文章,不僅函數挺有用的,而且設計思想也啓發了我——從常見事物中發現規律,提取抽象出通用的規則,能簡化流程提升效率

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

介紹

首先解釋一下這兩個概念:

函數節流(throttle):是讓一個函數無法在很短的時間間隔內連續調用,當上一次函數執行後過了規定的時間間隔,才能進行下一次該函數的調用。

函數去抖(debounce):讓一個函數在一定間隔內沒有被調用時,纔開始執行被調用方法。

兩個方法都是用來提升前端性能,減輕瀏覽器壓力。

應用

理解起來有點費力,通過應用來理解就輕鬆了。通常,我們會在有用戶交互參與的地方添加事件,而往往這種事件會被頻繁觸發。

  • 想象一下窗口的resize事件或者是一個元素的onmousemove事件,resize會在改變瀏覽器大小事連續觸發、onmousemove會在鼠標移動時被連續觸發,如果你的回調過重,你可能使瀏覽器死掉。
  • 想象一下你需要在用戶輸入一段文字時對文字進行處理,你監聽文字改變,每一次改變都會調用一次回調函數,其實我需要的是在用戶輸入停下來的時候去處理一次。
  • 射擊遊戲中你希望1s中之內只能發射一顆子彈,而不是用戶每按一次發射就發射。

類似的應用還有很多,throttle和debounce的區別就是在頻繁的回調中,throttle以一定頻率運行,而debounce在頻繁回調之後運行。總的來說就是過濾頻繁觸發的事件回調,使其在真正需要的時候執行,兩者根據應用場景自行選擇。

實現

說了這麼多,怎麼使用debounce和throttle功能呢,偉大的 http://underscorejs.org 給我們實現好了這兩個方法,這兩個方法的實現都是不依賴於其他underscore方法的,所以我們可以輕易的添加到其他JavaScript庫中,比如jQuery。

debounce   

這裏暫時不考慮immediate,有興趣可以自己研究。

函數去抖的基本思想是:對需要去抖的函數做包裝,使用閉包記錄timeout,第一次回調給函數設置 setTimeout定時器,只要在wait時間內,後一次的回調會clearTimeout取消前一次回調的執行。

_.debounce = function(func, wait, immediate) {
    var timeout, result;
    return function() {
      var context = this, args = arguments;
      var later = function() {
        timeout = null;
        if (!immediate) result = func.apply(context, args);
      };
      var callNow = immediate && !timeout;
      clearTimeout(timeout);
      timeout = setTimeout(later, wait);
      if (callNow) result = func.apply(context, args);
      return result;
    };
  };

throttle 

函數節流的基本思想是:無視瀏覽器的回調,自己按一定頻率執行代碼。

_.throttle = function(func, wait) {
    var context, args, timeout, result;
    var previous = 0;
    var later = function() {
      previous = new Date;
      timeout = null;
      result = func.apply(context, args);
    };
    return function() {
      var now = new Date;
      var remaining = wait - (now - previous);
      context = this;
      args = arguments;
      if (remaining <= 0) {
        clearTimeout(timeout);
        timeout = null;
        previous = now;
        result = func.apply(context, args);
      } else if (!timeout) {
        timeout = setTimeout(later, remaining);
      }
      return result;
    };
  };

 

參考資料:

1.JavaScript高級程序設計

2.http://www.cnblogs.com/ambar/archive/2011/10/08/throttle-and-debounce.html


原文地址http://www.cnblogs.com/friskfly/p/3175077.html#3161348


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章