从简入繁:详解 JS 柯里化,实现 add(1, 2)(3)(4, …)(5, …)… 无限累加函数。
什么是柯里化
- 官方定义:把一个接收多个参数的函数,设计成一个:接收单一参数的函数,并返回一个能够接收剩余参数的新函数,最后返回结果。
- 简单理解:调用函数A运行后返回函数B,B处理A剩余参数并返回函数C,C处理B剩余参数并返回函数D,...,最后返回结果。
// 普通函数 const add = (a, b, c) => { return a + b + c }
// 柯里化函数
const curry_add = (a) => { return (b) => { return (c) => { return a + b + c } } }
改造和拆解
1. 简单的递归函数
const curry_add = (a) => { return curry_add }
curry_add(1)(2)(3)(4)...
- 思考:返回递归函数的同时,如何将每次执行结果的值存储在函数中?
2. 像极了闭包和记忆函数
const curry_add=(a)=>{
let num =a||0
const item=(b)=>{
num+=b;
return item
}
return item
}
在 curry_add 函数被初次调用时,创建了一个拥有 num 变量 和 item 函数 的作用域函数,在第二次和后面的执行过程中,只是一直在 累计 num 和 调用 item 的重复工作,直到 curry_add 函数执行结束并销毁 num 和 item。
- 思考:如果将结果传递透出?
3. 不那么严谨的万物皆对象(简单实现)
const curry_add = (a) => {
let num = a || 0
const item = (b) => {
num+= b
item.num = num // 将 num 赋到函数上
return item
}
return item
}
-
思考:如何在执行结束后返回结果而中间步骤返回函数?
const curry_add = (a) => { let num = a || 0 const item = (b) => { num+= b return item } item.toString = () => { console.log('参数变化,自动触发') return num } return item } -
官方说明:Object.prototype.toString() 方法返回一个表示该对象的字符串,当对象被表示为文本值时 或者当以期望字符串的方式引用对象时,该方法被自动调用。
5. 展开运算符 ...
const curry_add=(...a)=>{
let num=a.reduce((t,c)=>{t+c,0})
const item =(...b)=>{
num=num+b.reduce((t,c)=>{t+c},0)
return item
}
item.toString=()=>num
return item
}
初次执行用 reduce 计算结果,在递归函数中也加入 reduce 累加结果,reduce 为函数基本操作,无内容补充