文章目录[隐藏]
在一些时候,我们可以用一些高阶函数,也就是返回一个函数的函数,来实现一些比较高级的操作,比如说使某个方法只执行一次,或者限制执行的频率
Once 只执行一次
function once(fn) { return function (...args) { if (fn) { const ret = fn.apply(this, args); fn = null; return ret; } } }
Throttle 限流函数
执行一次之后必须等待一段时间才能再执行
function throttle(fn, time = 500) { let timer; return function (...args) { if (timer == null) { fn.apply(this, args); timer = setTimeout(() => { timer = null; }, time) } } }
Debounce 去抖
防止在指定时间段内多次触发函数,等待稳定(最后一次触发之后一定时间内没有再触发)才执行
function debounce(fn, dur) { dur = dur || 100; var timer; return function () { clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, arguments); }, dur); } }
Consumer 执行之间的最小间隔
方法每次调用必须至少间隔指定的时间,要是提前调用了,就先存起来,等到时间到了再调用。
与 Debounce 的区别就是,Debounce 在多次调用时会把多出来的舍弃掉,而 Consumer 会存起来慢慢调用
function consumer(fn, time) { let tasks = [], timer; return function (...args) { tasks.push(fn.bind(this, ...args)); if (timer == null) { timer = setInterval(() => { tasks.shift().call(this) if (tasks.length <= 0) { clearInterval(timer); timer = null; } }, time) } } }
Iterative
可以把一个普通的函数变成批量的,可以遍历第一个参数来执行
const isIterable = obj => obj != null && typeof obj[Symbol.iterator] === 'function'; function iterative(fn) { return function (subject, ...rest) { if (isIterable(subject)) { const ret = []; for (let obj of subject) { ret.push(fn.apply(this, [obj, ...rest])); } return ret; } return fn.apply(this, [subject, ...rest]); } }
Toggle
可以循环执行多个函数,切换状态
function toggle(...actions) { return function (...args) { // 先将第一个操作取出,然后再将其 push 到列表的末尾,因此可以实现循环 const action = actions.shift(); actions.push(action); return action.apply(this, args); } }