2022/01/27

在一些时候,我们可以用一些高阶函数,也就是返回一个函数的函数,来实现一些比较高级的操作,比如说使某个方法只执行一次,或者限制执行的频率

Once 只执行一次

1function once(fn) { 2 return function (...args) { 3 if (fn) { 4 const ret = fn.apply(this, args); 5 fn = null; 6 return ret; 7 } 8 } 9}

Throttle 限流函数

执行一次之后必须等待一段时间才能再执行

1function throttle(fn, time = 500) { 2 let timer; 3 return function (...args) { 4 if (timer == null) { 5 fn.apply(this, args); 6 timer = setTimeout(() => { 7 timer = null; 8 }, time) 9 } 10 } 11}

Debounce 去抖

防止在指定时间段内多次触发函数,等待稳定(最后一次触发之后一定时间内没有再触发)才执行

1function debounce(fn, dur) { 2 dur = dur || 100; 3 var timer; 4 return function () { 5 clearTimeout(timer); 6 timer = setTimeout(() => { 7 fn.apply(this, arguments); 8 }, dur); 9 } 10}

Consumer 执行之间的最小间隔

方法每次调用必须至少间隔指定的时间,要是提前调用了,就先存起来,等到时间到了再调用。

与 Debounce 的区别就是,Debounce 在多次调用时会把多出来的舍弃掉,而 Consumer 会存起来慢慢调用

1function consumer(fn, time) { 2 let tasks = [], 3 timer; 4 5 return function (...args) { 6 tasks.push(fn.bind(this, ...args)); 7 if (timer == null) { 8 timer = setInterval(() => { 9 tasks.shift().call(this) 10 if (tasks.length <= 0) { 11 clearInterval(timer); 12 timer = null; 13 } 14 }, time) 15 } 16 } 17}

Iterative

可以把一个普通的函数变成批量的,可以遍历第一个参数来执行

1const isIterable = obj => obj != null 2 && typeof obj[Symbol.iterator] === 'function'; 3 4function iterative(fn) { 5 return function (subject, ...rest) { 6 if (isIterable(subject)) { 7 const ret = []; 8 for (let obj of subject) { 9 ret.push(fn.apply(this, [obj, ...rest])); 10 } 11 return ret; 12 } 13 return fn.apply(this, [subject, ...rest]); 14 } 15}

Toggle

可以循环执行多个函数,切换状态

1function toggle(...actions) { 2 return function (...args) { 3 // 先将第一个操作取出,然后再将其 push 到列表的末尾,因此可以实现循环 4 const action = actions.shift(); 5 actions.push(action); 6 return action.apply(this, args); 7 } 8}

Code credits to 月影blog 好像炸了qwq)