高阶函数 - Higher Order Function
一个函数如果有 参数是函数 或 返回值是函数,就称为高阶函数。
这篇文章介绍高阶函数的一个子集:输入 fn
,输出 fn'
。按 fn
与 fn'
功能是否一致,即相同输入是否始终对应相同输出,把这类高阶函数的作用分为两种:
- 包装函数:功能一致
- 修改函数:功能不一致
包装函数
从斐波那契数列开始。
const fib = n =>
n <= 1 ? 1 : fib(n - 1) + fib(n - 2);
fib(42);
记录执行时间
普通青年
const fib = n =>
n <= 1 ? 1 : fib(n - 1) + fib(n - 2); console.time("fib");
fib(42);
console.timeEnd("fib");
函数式青年
const timed = fn => (...args) => {
console.time(fn.name);
const result = fn(...args);
console.timeEnd(fn.name);
return result;
};
const fib = n =>
n <= 1 ? 1 : fib(n - 1) + fib(n - 2); timed(fib)(42);
优化性能
普通青年
const memory = {};
const fib = n => {
if (n <= 1) return 1;
else {
if (memory[n]) return memory[n];
else {
memory[n] = fib(n - 1) + fib(n - 2);
return memory[n];
}
}
};
const timed = fn => (...args) => {
console.time(fn.name);
const result = fn(...args);
console.timeEnd(fn.name);
return result;
};
timed(fib)(42);
函数式青年
const memoize = fn => {
const memory = {};
return arg => {
if (memory[arg]) return memory[arg];
else {
memory[arg] = fn(arg);
return memory[arg];
}
};
};
const fib = memoize(n =>
n <= 1 ? 1 : fib(n - 1) + fib(n - 2)
);
const timed = fn => (...args) => {
console.time(fn.name);
const result = fn(...args);
console.timeEnd(fn.name);
return result;
};
timed(fib)(42);
修改函数
once
场景:
发送请求,如果后台返回 session 超时,弹出重新登录提示框。
发出多个请求,都 session 超时,只希望弹一个重新登录提示框。
const once = fn => {
let executed = false;
return (...args) => {
if (!executed) {
executed = true;
fn(...args);
}
};
};
const showLogoutWin = once(() => {
// ...
});
debounce
场景:
输入框 change 事件触发向后台查询。
为消除不必要查询,用户连续输入时不触发查询,
当 200ms 内没有新的输入时,才向后台查询。
const debounce = (fn, ms = 200) => {
let timeoutId;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn(...args), ms);
};
};
更多实际场景
validateRequired
场景:
根据rule.required
判断空值时是否报错,
这段逻辑出现在多个 validator 中。
const ipv4Validator = (rule, value, callback) => {
if (value) {
if (ipv4RegExp.test(value)) {
callback();
} else {
callback("请输入合法IP");
}
} else {
if (rule.required) {
callback("该域为必填项");
} else {
callback();
}
}
};
把判空的逻辑提取到高阶函数中:
const validateRequired = (
validator,
msg = "该域为必填项"
) => (rule, value, callback) => {
if (value) {
validator(rule, value, callback);
} else {
if (rule.required) {
callback(msg);
} else {
callback();
}
}
};
const ipv4Validator = validateRequired(
(rule, value, callback) => {
if (ipV4Regexp.test(value)) {
callback();
} else {
callback("请输入合法IP");
}
}
);
tryUntilSucceeded
场景:
因为网络不稳定,请求可能出错。
出错后重新请求,直到得到响应为止。
let res;
while (true) {
try {
res = await get(path);
break;
} catch (err) {
console.log(err);
}
}
把出错重试的逻辑提取到高阶函数中:
const tryUntilSucceeded = fn => async (
...args
) => {
while (true) {
try {
return await fn(...args);
} catch (err) {
console.log(err);
}
}
};
const enhancedGet = tryUntilSucceeded(get);
const enhancedPost = tryUntilSucceeded(post);
const resGet = await enhancedGet(path);
const resPost = await enhancedPost(path);
小结
两个代码块一样,把这个代码块提取出来,封成一个函数,减少代码重复,这个技巧大家都知道;两段代码流程一样,用高阶函数把公共流程提取出来,减少代码重复,这个技巧知道的人就不多了。可以类比 react 高阶组件,道理是一样的。
高阶函数 - Higher Order Function的更多相关文章
- Python进阶内容(一)--- 高阶函数 High order function
0. 问题 # 本文将围绕这段代码进行Python中高阶函数相关内容的讲解 # 文中所有代码的兼容性要求为:Python 3.6,IPython 6.1.0 def addspam(fn): def ...
- 高阶函数(Higher-order function)
变量可以指向函数 以Python内置的求绝对值的函数abs()为例,调用该函数用以下代码: >>> abs(-15) 15 但是,如果只写abs呢? >>> abs ...
- 匿名方法,Lambda表达式,高阶函数
原文:匿名方法,Lambda表达式,高阶函数 匿名方法 c#2.0引入匿名方法,不必创建单独的方法,因此减少了所需的编码系统开销. 常用于将委托和匿名方法关联,例如1. 使用委托和方法关联: this ...
- 《JS权威指南学习总结--8.8.2高阶函数》
内容要点: 所谓高阶函数(higher-order function)就是操作函数的函数,它接收一个或多个函数作为参数,并返回一个新函数. 例1: //这个高阶函数返回一个新的函数,这个新函数将它的实 ...
- python---内置函数,匿名函数,嵌套函数,高阶函数,序列化
函数简单说明 # 函数即"变量" # 高阶函数 # a.把一个函数名当做实参传给另一个函数(在不修改被装饰函数的源代码的情况下,为其添加功能) # b.返回值中包含函数名(不修改函 ...
- 理解运用JS的闭包、高阶函数、柯里化
JS的闭包,是一个谈论得比较多的话题了,不过细细想来,有些人还是理不清闭包的概念定义以及相关的特性. 这里就整理一些,做个总结. 一.闭包 1. 闭包的概念 闭包与执行上下文.环境.作用域息息相关 执 ...
- python的高阶函数与匿名函数
一.高阶函数的定义 高阶函数:就是把函数当成参数传递的一种函数,例如: def add(x,y,f): return f(x)+f(y) print(add(-8,11,abs) 结果:19 解释: ...
- Javascript中的高阶函数介绍
高阶函数:高阶看上去就像是一种先进的编程技术的一个深奥术语,一开始我看到的时候我也这样认为的. Javascript的高阶函数 然而,高阶函数只是将函数作为参数或返回值的函数.以下面的Hello,Wo ...
- Swift 烧脑体操(三) - 高阶函数
前言 Swift 其实比 Objective-C 复杂很多,相对于出生于上世纪 80 年代的 Objective-C 来说,Swift 融入了大量新特性.这也使得我们学习掌握这门语言变得相对来说更加困 ...
随机推荐
- 小白的springboot之路(一)、环境搭建、第一个实例
小白的springboot之路(一).环境搭建.第一个实例 0- 前言 Spring boot + spring cloud + vue 的微服务架构技术栈,那简直是爽得不要不要的,怎么爽法,自行度娘 ...
- js消除小游戏(极简版)
js小游戏极简版 (1) 基础布局 <div class = "box"> <p></p> <div class="div&qu ...
- 最小生成树与最短路径--C语言实现
接昨天,在这里给出图的其中一种应用:最小生成树算法(Prime算法和Kruskal算法).两种算法的区别就是:Prime算法以顶点为主线,适合用于顶点少,边密集的图结构:Kruskal算法以边为主线, ...
- 使用jieba分析小说太古神王中,男主更爱谁?去文章中找答案吧!#华为云·寻找黑马程序员#
欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...
- AI如何驱动软件开发?华为云DevCloud 权威专家邀你探讨
近期,国际著名咨询公司Gartner 在一份研究报告中将 "AI-Driven Development" 列为 2019 年的 Top 10 Strategic Technolog ...
- 简单理解http协议的特性
http协议一种数据传输的规范,像我们的在发送数据的时候,我们无法保证发送与接收的类型是一致的,它就保证了我们传输的同一个类型数据. 特性: 1.灵活:我们不管传输什么数据,图片,文件,文字,都可以进 ...
- win7系统的用户去掉用户账户控制 提升管理员
可以在组策略中进行设置 —— “以管理员身份运行”方式打开命令提示符(CMD)后键入 gpedit.msc 打开组策略后作如下更改:<br/>在“计算机配置”-“Windows 配置”-“ ...
- POJ-1743 Musical Theme(最长不可重叠子串,后缀数组+二分)
A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the ...
- 拓展KMP分析
拓展kmp是对KMP算法的扩展,它解决如下问题: 定义母串S,和字串T,设S的长度为n,T的长度为m,求T与S的每一个后缀的最长公共前缀,也就是说,设extend数组,extend[i]表示T与S[i ...
- A*算法在最短路问题的应用及其使用举例
1 A*算法 A*算法在人工智能中是一种典型的启发式搜索算法,启发中的估价是用估价函数表示的: 其中f(n)是节点n的估价函数,g(n)表示实际状态空间中从初始节点到n节点的实际代价,h(n)是从n到 ...