写点什么

手写柯里化 - toString 理解

作者:掘金安东尼
  • 2022 年 8 月 05 日
  • 本文字数:1087 字

    阅读完需:约 4 分钟

手写柯里化 - toString 理解

柯里化可以通过闭包+递归实现


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)() // 6addCurry(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 日更文 ✍ 陪你一起度过漫长岁月 🌏

发布于: 19 小时前阅读数: 27
用户头像

安东尼陪你度过漫长编程岁月~ 2022.07.14 加入

社会我瓜哥,人狠话不多😎 微信 anthony1453,加我交个朋友😎 正联合【机械工业出版社】出版《程序员成长手册》,敬请期待😎 真正的大师,永远怀着一颗学徒的心(易)😎

评论

发布
暂无评论
手写柯里化 - toString 理解_JavaScript_掘金安东尼_InfoQ写作社区