快速介紹幾個JS函數

JS中函數是一等公民,地位很高。本文介紹快速介紹三個函數:redux

  • throttle 節流函數
  • debounce 去抖函數
  • compose 組合函數,這函數就是把一系列函數按順序一個個執行。

節流和去抖函數

當某些事件頻繁觸發形成不斷執行DOM操做或資源加載等行爲,這時你可能就會想到用節流和去抖函數來處理。數組

throttle 節流函數

節流函數就是預先設定一個執行週期,當調用動做的時刻大於等於執行週期則執行該動做,而後進入下一個新週期。app

能夠用在下面兩個情景中:ide

  • window對象的resize、scroll事件
  • 拖拽時的mousemove事件

簡單實現函數

function throttle (fn, delay) {
    let last = 0
    return (...args) => {
        const now = Date.now()
        if (now - last > delay) {
            fn.call(this, args)
            last = now
        }
    }
}
複製代碼

debounce 去抖函數

去抖函數就是調用動做n毫秒後,纔會執行該動做,若在這n毫秒內又調用此動做則將從新計算執行時間。ui

一般用在下面的場景中:this

  • 文字輸入、自動完成的keyup事件

簡單實現spa

function debounce (fn, delay) {
    let last = 0
    return (...args) => {
        clearTimeout(last)
        last = setTimeout(() => {
            fn.call(this, args)
        }, delay)
    }
}
複製代碼

這邊找了一個網上的實現版本:3d

/* * 頻率控制 返回函數連續調用時,fn 執行頻率限定爲每多少時間執行一次 * @param fn {function} 須要調用的函數 * @param delay {number} 延遲時間,單位毫秒 * @param immediate {bool} 給 immediate參數傳遞false 綁定的函數先執行,而不是delay後後執行。 * @return {function}實際調用函數 */
var throttle = function (fn,delay, immediate, debounce) {
   var curr = +new Date(),//當前事件
       last_call = 0,
       last_exec = 0,
       timer = null,
       diff, //時間差
       context,//上下文
       args,
       exec = function () {
           last_exec = curr;
           fn.apply(context, args);
       };
   return function () {
       curr= +new Date();
       context = this,
       args = arguments,
       diff = curr - (debounce ? last_call : last_exec) - delay;
       clearTimeout(timer);
       if (debounce) {
           if (immediate) {
               timer = setTimeout(exec, delay);
           } else if (diff >= 0) {
               exec();
           }
       } else {
           if (diff >= 0) {
               exec();
           } else if (immediate) {
               timer = setTimeout(exec, -diff);
           }
       }
       last_call = curr;
   }
};
 
/* * 空閒控制 返回函數連續調用時,空閒時間必須大於或等於 delay,fn 纔會執行 * @param fn {function} 要調用的函數 * @param delay {number} 空閒時間 * @param immediate {bool} 給 immediate參數傳遞false 綁定的函數先執行,而不是delay後後執行。 * @return {function}實際調用函數 */
 
var debounce = function (fn, delay, immediate) {
   return throttle(fn, delay, immediate, true);
};
複製代碼

本身畫了一張圖便於理解,最左邊的boolean值是上邊的immediate值,沿x軸的線是時間線,時間線上面是用戶觸發的動做,下面是函數的執行。code

上面函數有點奇怪的地方就是immediate參數傳遞false 綁定的函數先執行

先看debounceimmediate不一樣的狀況下的表現:

immediatefalse的狀況下,第一次觸發動做,函數就立刻被執行了,後續的在delay時間段內重複按鍵都不會觸發函數,並且會重置delay開始計算的時間點。當觸發動做間隔時間超過delay後,又回到了初始狀態,一觸發動做就執行函數。

immediatetrue的狀況下,觸發動做後,函數並無立刻執行,只有在通過delay時間段內,沒有觸發動做時,函數纔會被執行。

接着看throttleimmediate不一樣的狀況下的表現:

immediatefalse的狀況下,第一次觸發動做,函數就立刻被執行了,在此次執行後,在後續的delay時間段內觸發動做都不會執行函數,間隔大於delay後,回到初始狀態,觸發動做函數就執行。

immediatetrue的狀況下,第一次觸發動做,函數就立刻被執行了,同時定時器設置延時delay時間後在執行函數。其實和上面狀況差很少,只不過會在delay後多執行一次。固然還有一些細節不一樣,圖中能夠看到,有兩個執行之間時間並無間隔delay。

compose函數

這個直接上代碼了,是從redux那邊借過來的。

/** * Composes single-argument functions from right to left. The rightmost * function can take multiple arguments as it provides the signature for * the resulting composite function. * * @param {...Function} funcs The functions to compose. * @returns {Function} A function obtained by composing the argument functions * from right to left. For example, compose(f, g, h) is identical to doing * (...args) => f(g(h(...args))). */

export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
複製代碼

核心代碼就一行,沒錯,就一行。

沒看到以前,我可能會經過for循環來作,上面代碼用到數組方法reduce,在配合剩餘參數語法和擴展運算符...來傳參就能夠實現函數組合的功能,很是精簡。

介紹到這裏就結束了,後續碰到到驚豔的函數還會繼續分享。

相關文章
相關標籤/搜索