函數節流

JavaScript中的函數大多數狀況下都是由用戶主動調用觸發的,除非是函數自己的實現不合理,不然咱們通常不會遇到跟性能相關的問題。但在一些少數狀況下,函數的觸發不是由用戶直接控制的。在這些場景下,函數有可能被很是頻繁地調用,而形成大的性能問題。下面將列舉一些這樣的場景。瀏覽器

(1) 函數被頻繁調用的場景app

  • window.onresize事件。咱們給window對象綁定了resize事件,當瀏覽器窗口大小被拖動而改變的時候,這個事件觸發的頻率很是之高。若是咱們在window.onresize事件函數裏有一些跟DOM節點相關的操做,而跟DOM節點相關的操做每每是很是消耗性能的,這時候瀏覽器可能就會吃不消而形成卡頓現象。函數

  • mousemove事件。一樣,若是咱們給一個div節點綁定了拖曳事件(主要是mousemove),當div節點被拖動的時候,也會頻繁地觸發該拖曳事件函數。性能

  • 上傳進度。微雲的上傳功能使用了公司提供的一個瀏覽器插件。該瀏覽器插件在真正開始上傳文件以前,會對文件進行掃描並隨時通知JavaScript函數,以便在頁面中顯示當前的掃描進度。但該插件通知的頻率很是之高,大約一秒鐘10次,很顯然咱們在頁面中不須要如此頻繁地去提示用戶。this

(2) 函數節流的原理spa

咱們整理上面提到的三個場景,發現它們面臨的共同問題是函數被觸發的頻率過高。插件

好比咱們在window.onresize事件中要打印當前的瀏覽器窗口大小,在咱們經過拖曳來改變窗口大小的時候,打印窗口大小的工做1秒鐘進行了10次。而咱們實際上只須要2次或者3次。這就須要咱們按時間段來忽略掉一些事件請求,好比確保在500ms內只打印一次。很顯然,咱們能夠藉助setTimeout來完成這件事情。code

(3) 函數節流的代碼實現對象

關於函數節流的代碼實現有許多種,下面的throttle 函數的原理是,將即將被執行的函數用setTimeout延遲一段時間執行。若是該次延遲執行尚未完成,則忽略接下來調用該函數的請求。throttle函數接受2個參數,第一個參數爲須要被延遲執行的函數,第二個參數爲延遲執行的時間。具體實現代碼以下:blog

var throttle = function ( fn, interval ) {

    var __self = fn,    // 保存須要被延遲執行的函數引用
        timer,      // 定時器
        firstTime = true;    // 是不是第一次調用

    return function () {
        var args = arguments,
            __me = this;

        if ( firstTime ) {    // 若是是第一次調用,不需延遲執行
            __self.apply(__me, args);
            return firstTime = false;
        }

        if ( timer ) {    // 若是定時器還在,說明前一次延遲執行尚未完成
            return false;
        }

        timer = setTimeout(function () {  // 延遲一段時間執行
            clearTimeout(timer);
            timer = null;
            __self.apply(__me, args);

        }, interval || 500 );

    };

};

window.onresize = throttle(function(){
    console.log( 1 );
}, 500 );
相關文章
相關標籤/搜索