这是我参与「第四届青训营 」笔记创作活动的第2天
一些常用的高阶函数分享~~~
高阶函数(HOF)
以函数作为参数,以函数作为返回值,通常用于装饰器。 其一般形式为👇
function HOF(fn) {
return function(...args) {
return fn.apply(this, args);
}
}
如果没有添加其他 js 语句,执行 HOF(fn)() 与执行 fn() 是一样的。 使用高阶函数有助于进行过程抽象,将原本的非纯函数转化为纯函数,防止对外界造成干扰。
常用的高阶函数有:Once, throttle, debounce。
Once —— 只执行一次
在一些只想执行一次代码的场合,比如为 button 添加点击事件,2秒后删除本节点,这时候如果重复点击 button 就会报错,使用 Once 函数可以解决这个问题,只能点击一次。
function once(fn) {
return function(...args) {
if (fn) {
let res = fn.apply(this, args);
fn = null;
return res;
}
}
}
throttle —— 节流函数
在一段时间内只执行一次,重复触发无效,通常用于鼠标移动等连续触发的事件中,可以很好的节约性能。 节流函数有两种实现方式,一种根据时间戳,一种利用定时器。
// 时间戳写法
function throttle(fn, wait) {
let pre = +new Date();
return function (...args) {
let now = +new Date();
if (now - pre >= wait) {
pre = now;
return fn.apply(this, args);
}
}
}
// 定时器写法
function throttle(fn, wait) {
let timer = null;
return function (...args) {
if (!timer) {
timer = setTimeout(() => {
timer = null;
}, wait);
return fn.apply(this, args);
}
}
}
debounce —— 防抖函数
同样是一段时间内只执行一次,与节流的区别是:节流函数在指定时间段内不断触发一定会执行一次,而防抖函数如果不停触发,每次都会重新计时,直到指定时间段内没有新的触发。两次执行的时间间隔至少是指定时间。
function debounce(fn, wait) {
let timer = null;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => {
return fn.apply(this, args);
}, wait);
}
}
此时的防抖函数第一次触发时是不执行的,延时时间结束才会执行。如果希望第一次能够执行,可以添加一个 immediate 参数👇
function debounce(fn, wait, immediate = false) {
let timer = null;
return function (...args) {
clearTimeout(timer);
if (!immediate) {
timer = setTimeout(() => {
return fn.apply(this, args);
}, wait);
} else {
let flag = !timer;
timer = setTimeout(() => {
timer = null;
}, wait);
if (flag) {
return fn.apply(this, args);
}
}
}
}
consumer —— (emmmm,不知道应该叫什么名字,但是很厉害的一个函数)
将每次触发的函数存在一个队列中,按照指定的时间依次调用,不会丢失其中的任一触发。
function consumer(fn, time) {
let tast = [];
let timer = null;
return function(...args) {
tast.push(fn.bind(this, ...args));
if (timer === null) {
timer = setInterval(() => {
tast.shift().call(this);
if (tast.length <= 0) {
clearInterval(timer);
timer = null;
}
}, time);
}
}
}