常用HOF | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的第5天
引入
HOF——即高阶函数,那么何为高阶函数?一个函数就可以接收另一个函数作为参数或者返回值为一个函数,这种函数就称之为高阶函数。例如,数组中的高阶函数如:map、filter、reduce、sort,都是以函数为参数对数组进行操作,大致的HOF函数框架如下:
// 高阶函数框架
function HOF0(fn) {
// 内外两个函数效果是等价的
return function (...args) {
// 会加了一些操作
return fn.apply(this, args);
}
}
HOF特点
- 以函数作为参数
- 以函数作为返回值
- 常用于作为函数装饰器
简单案例
Once函数:判断一个操作只执行一次
// 高阶函数:调用一个函数会return一个另一个函数
function once(fn) {
// outer scape closure ...【形成一个闭包】
return function (...args) {
// inner scape【只执行一次】
if (fn) {
const ret = fn.apply(this, args);
fn = null; // 置空则下次执行不了
return ret;
}
}
}
为了能够让“只执行一次”的需求覆盖不同的事件处理,我们可以将这个需求剥离出来。这个过程我们称为过程抽象。
常用HOF
- 节流阀throttle
/**
*
* @param {*} fn 要进行节流操作的函数【写函数参数时无论是箭头函数还是普通函数格式,最后的this指向都一样是window】
* @param {*} time 控制触发的间隔时间
* @returns
*/
function throttle(fn, time = 500) {
let timer;
return function (...args) { // 这里若是改为箭头函数则this会向外找对象window
if (timer == null) {
fn.apply(this, args);
// 触发一个定时器使得函数保持在一段时间后再触发
timer = setTimeout(() => { // 注意这里必须为箭头函数,否则若是fn.apply()写在其下则会指向window
timer = null;
}, time)
}
}
}
- 防抖debounce
/**
* 【例子:隔几秒进行自动保存/鼠标移动小鸟跟着移动】
* @param {*} fn 要进行防抖操作的函数【永远只执行最后一次调用】
* @param {*} dur 控制间歇时间
* @returns
*/
function debounce(fn, dur) {
dur = dur || 100;
var timer;
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, dur);
}
}
- 迭代器Iterator
/**
* iterative()先由isIterable()函数来分析是否为可迭代对象然后再进行后续操作
* @param {*} fn 将可迭代对象的子元素挨个进行操作【jq的API有提供类似的操作】
* @returns
*/
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]);
}
}
// 案例:实现给所有的els加颜色
const setColor = iterative((el, color) => {
el.style.color = color;
});
const els = document.querySelectorAll('li:nth-child(2n+1)');
setColor(els, 'red');
为什么要使用高阶函数
-
纯函数:简单,无特殊输入,结果可预期;【高阶函数是纯函数 => 输入输出是固定的】
-
非纯函数:复杂,检测难【需要使用外部的参数 or 一个函数又依赖另外一个函数,需要检测多个函数】,因此鼓励使用纯函数【即高阶函数】,可以大大的提高可维护性