快速介绍几个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,在配合剩余参数语法和扩展运算符...来传参就能够实现函数组合的功能,很是精简。

介绍到这里就结束了,后续碰到到惊艳的函数还会继续分享。

相关文章
相关标签/搜索