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
,在配合剩余参数语法和扩展运算符...
来传参就能够实现函数组合的功能,很是精简。
介绍到这里就结束了,后续碰到到惊艳的函数还会继续分享。