JS中函數是一等公民,地位很高。本文介紹快速介紹三個函數:redux
throttle
節流函數debounce
去抖函數compose
組合函數,這函數就是把一系列函數按順序一個個執行。當某些事件頻繁觸發形成不斷執行DOM操做或資源加載等行爲,這時你可能就會想到用節流和去抖函數來處理。數組
throttle
節流函數節流函數就是預先設定一個執行週期,當調用動做的時刻大於等於執行週期則執行該動做,而後進入下一個新週期。app
能夠用在下面兩個情景中:ide
簡單實現函數
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
簡單實現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
綁定的函數先執行。
先看debounce
在immediate
不一樣的狀況下的表現:
在immediate
爲false
的狀況下,第一次觸發動做,函數就立刻被執行了,後續的在delay時間段內重複按鍵都不會觸發函數,並且會重置delay開始計算的時間點。當觸發動做間隔時間超過delay後,又回到了初始狀態,一觸發動做就執行函數。
在immediate
爲true
的狀況下,觸發動做後,函數並無立刻執行,只有在通過delay時間段內,沒有觸發動做時,函數纔會被執行。
接着看throttle
在immediate
不一樣的狀況下的表現:
在immediate
爲false
的狀況下,第一次觸發動做,函數就立刻被執行了,在此次執行後,在後續的delay時間段內觸發動做都不會執行函數,間隔大於delay後,回到初始狀態,觸發動做函數就執行。
在immediate
爲true
的狀況下,第一次觸發動做,函數就立刻被執行了,同時定時器設置延時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
,在配合剩餘參數語法和擴展運算符...
來傳參就能夠實現函數組合的功能,很是精簡。
介紹到這裏就結束了,後續碰到到驚豔的函數還會繼續分享。