当前位置:网站首页>手写柯里化 - toString 理解
手写柯里化 - toString 理解
2022-08-05 09:14:00 【InfoQ】
柯里化可以通过闭包+递归实现
let arr = []
function addCurry() {
let arg = Array.prototype.slice.call(arguments); // 收集参数
arr = arr.concat(arg);
if (arg.length === 0) { // 如果参数为空,则判断递归结束
return arr.reduce((a,b)=>{return a+b}) // 求和
} else {
return addCurry;
}
}
addCurry(1)(2)(3)() // 6
这样写,没什么毛病,通过:
Array.prototype.slice.call(arguments)
收集了参数,推到
arr
数组里;当存在参数时,递归调用,当没有参数的时候,再用
reduce()
求和,返回;
但是这样写,会有外部变量 arr,arr 不清理的话,会被一直保存,导致连续调用出错:
addCurry(1)(2)(3)() // 6
addCurry(1)() // 7
所以,需要改写成这样:
function addCurry() {
let arr = [...arguments]
let fn = function () {
if(arguments.length === 0) {
return arr.reduce((a, b) => a + b)
} else {
arr.push(...arguments)
return fn
}
}
return fn
}
把 arr 再加一层封装到函数里,每次调用,都会重新声明,原值会被清理;
之前相加的思路仍然不变;
但这样做,还有一个问题:总是需要用空括号 () 为结尾,来判断结束调用;
能不能去掉这个,直接如下这样就能求值:
addCurry(1)(2)(3)
//或
addCurry(1)(2,3)
答案是可以的,原理是用到
toString
,当用 Function 的值做计算的时候,会调用 toString 做隐式转换;
let fn = function(){}
fn.toString = () => 1
fn == 1 // true
所以,我们的代码更新为:
function addCurry() {
let arr = [...arguments]
// 利用闭包的特性收集所有参数值
var fn = function() {
arr.push(...arguments);
return fn;
};
// 利用 toString 隐式转换
fn.toString = function () {
return arr.reduce(function (a, b) {
return a + b;
});
}
return fn;
}
addCurry(1)(2)(3) == 6 // true
这里一定要注意,直接打印 addCurry(1)(2)(3) 是不能拿值的,只有当它做隐式转化的时候,才能计算得正确得值。
小结:
其实不管是用空括号 () 作“开始执行reduce相加”的判断依据,还是用 toString 的隐式转换做依据,总是要有一个标准,来告诉柯里化函数:你可以执行了!
柯里化精髓是参数收集,是延迟执行!
延迟就是 JS 函数闭包的精髓设计!!
OK,以上便是本篇分享。点赞关注评论,为好文助力
我是掘金安东尼 100 万阅读量人气前端技术博主 INFP 写作人格坚持 1000 日更文 陪你一起度过漫长岁月
边栏推荐
- 百行代码发射红心,程序员何愁命不中女朋友!
- 2022.8.3
- js graphics operation one (compatible with pc, mobile terminal to achieve draggable attribute drag and drop effect)
- PAT Level B - B1021 Single Digit Statistics (15)
- 无题十三
- ECCV 2022 Oral 视频实例分割新SOTA:SeqFormer&IDOL及CVPR 2022 视频实例分割竞赛冠军方案...
- Excuse me, guys, is it impossible to synchronize two databases in real time using Flink SQL CDC?
- 2022-08-01 回顾基础二叉树以及操作
- 2022.8.3
- 2.4G无线收发模块的应用
猜你喜欢
随机推荐
DPU — 功能特性 — 网络系统的硬件卸载
只有一台交换机,如何实现主从自动切换之nqa
工程制图试题
Assembly language (8) x86 inline assembly
全面讲解GET 和 POST请求的本质区别是什么?原来我一直理解错了
无题十四
Luogu P1908: 逆序对 [树状数组]
CPU的亲缘性affinity
科普大佬说 | 港大黄凯斌老师带你解锁黑客帝国与6G的关系
“充钱”也难治快手的“亏亏亏”?
21 Days of Deep Learning - Convolutional Neural Networks (CNN): Weather Recognition (Day 5)
leetcode points to Offer 10- I. Fibonacci sequence
使用稀疏 4D 卷积对 3D LiDAR 数据中的运动对象进行后退分割(IROS 2022)
PAT乙级-B1019 数字黑洞(20)
手把手教你纯c实现异常捕获try-catch组件
SQL语句查询字段内重复内容,并按重复次数加序号
Luogu: P2574 XOR的艺术 [线段树]
无题十
pytorch余弦退火学习率CosineAnnealingLR的使用
sql server收缩日志的作业和记录,失败就是因为和备份冲突了吗?