underscore 源码解读之 function 的扩展方法部分即将进入尾声,我们重点剖析了解了 bind 方法的使用场景以及兼容方式,函数节流、函数去抖,以及 memoize 方法,本文我们来看看 underscore 还为 function 扩展了哪些有用(有意思)的方法。
.delay & .defer
_.delay 能使得函数延迟执行,其实就是封装了一个定时器。
// Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied.
// 延迟触发某方法
// _.delay(function, wait, *arguments)
// 如果传入了 arguments 参数,则会被当作 func 的参数在触发时调用
// 其实是封装了「延迟触发某方法」,使其复用
_.delay = function(func, wait) {
// 获取 *arguments
// 是 func 函数所需要的参数
var args = slice.call(arguments, 2);
return setTimeout(function(){
// 将参数赋予 func 函数
return func.apply(null, args);
}, wait);
};
_.defer 其实就是设定了一个 0ms 的定时器(源码中其实设定的是 1ms)
// Defers a function, scheduling it to run after the current call stack has
// cleared.
// 和 setTimeout(func, 0) 相似(源码看来似乎应该是 setTimeout(func, 1))
// _.defer(function, *arguments)
// 如果传入 *arguments,会被当做参数,和 _.delay 调用方式类似(少了第二个参数)
// 其实核心还是调用了 _.delay 方法,但第二个参数(wait 参数)设置了默认值为 1
// 如何使得方法能设置默认值?用 _.partial 方法
_.defer = _.partial(_.delay, _, 1);
underscore 源码解读之 function 的扩展方法部分即将进入尾声,我们重点剖析了解了 bind 方法的使用场景以及兼容方式,函数节流、函数去抖,以及 memoize 方法,本文我们来看看 underscore 还为 function 扩展了哪些有用(有意思)的方法。
.delay & .defer
_.delay 能使得函数延迟执行,其实就是封装了一个定时器。
_.defer 其实就是设定了一个 0ms 的定时器(源码中其实设定的是 1ms)
.partial 可以理解为一个「占位方法」,.delay 至少需要两个参数,第一个参数用
_
来占位( .defer 的参数),第二个参数为 1,表示 .delay 的 wait 参数为 1,也就是说设定了一个 1ms 的定时器。应用在哪里?其实平时你需要用到setTimeout(function(){}, 0)
的地方,都可以用 _.defer 方法代替,比如为了避免 UI 卡顿的场景。.after & .before & _.once
思考这样一个场景,如果有 N 个异步请求,全部请求完成后需要触发某个方法,怎么做?以前做爬虫碰到过这样的场景,当时用了 eventproxy 模块,ES6 的 Promise 应该也提供了相应的 API,underscore 的 _.after 方法也能做到。
如果不仔细看,可能会错误地使用(N 次之后每次都会执行方法)。
原来的文档有点问题,我报了个 bug https://github.com/jashkenas/underscore/issues/2607,提了个 pr https://github.com/jashkenas/underscore/pull/2608,被合并了。_.after 源码非常简单,就不贴了。
.before 和 .after 相反,其实两个方法的参数相同。假设传入第一个参数 times 的值为 N,.after 是在
[N, +∞)
次触发方法时执行,而 .before 是在[1, N)
触发时执行方法,刚好互为补集。也就是 _.before 应用于 至多触发某函数 N-1 次。
而 .once 基于 .before 进行了封装,用于某函数至多只能被执行一次的场景。
适用于类似初始化的场景,只需要被执行一次。