如何解释JS柯里化,对柯里化的简单理解是怎样
Admin 2022-08-11 群英技术资讯 352 次浏览
我们不妨以两数相加为例子,递进说明。
我们通常是这样写一个函数来求得 两数相加 的值:
function sum(a,b){ console.log(a+b) } sum(1,2)
这样写一点毛病没有!
不过呢?问题总会在发展中产生,产品经理又要加一个值,需求:三数相加;
咱通常来说,第一时间,就在原基础上,直接再加一个参数就是了;
于是,修改后像是这样:
function sum(a,b,c){ console.log(a+b+c) } sum(1,2,3)
问:这样写,有毛病吗??
答:太有毛病了!
这样一改,既违反了:“开闭原则”、又违反了:“单一职责原则”。
为不太熟悉设计原则的小伙伴们,简单解释下:
首先,咱修改了 sum 函数的传参以及内部的调用 ⇒ 则违反“开闭原则”
其次,sum 函数本来只负责两数相加,修改后,它又负责三数相加,职责已经发生了变化 ⇒ 则违反 “单一职责原则”;
如果正规按照单一责任来写,应该是:
// 负责两数相加 function sum2(a,b){ console.log(a+b) } // 负责三数相加 function sum3(a,b,c){ console.log(a+b+c) }
事实上,是不可能这样去写的,因为如果有一万个数相加,得写一万个函数。
而 加法只有一个!! 不管你最终要加几个值,总是要一个加一个。
于是乎,我们设想,能不能写一个这样的函数:它的功能,就是“加”,参数跟几个,我就加几个。
// 负责“加法”, function addCurry(){ ... ... ... } addCurry(1)(2) // 两数相加 addCurry(1)(2)(3) // 三数相加 ... addCurry(1)(2)(3)...(n) // n 数相加
没错,这个函数就是:柯里化!!(或者说这个过程叫柯里化,这个思想叫柯里化,本瓜认为这里不需要太死扣定义)
接着,我们一步步来试试,它会是怎样构成的?
为了能够实现一个加一个,即存储参数的目的,我们想一想,还有什么法宝?
没错,JS 奥义:闭包!
其实,本瓜时常想,闭包的终极秘密是什么?最后将其理解为 4 个金光闪闪的大字:延迟处理!
什么意思?简单解释下:
function directHandle(a,b){ console.log("直接处理",a,b) } directHandle(111,222) // 直接处理 111 222 function delayHandle(a){ return function(b){ console.log("延迟处理",a,b) } } delayHandle(111) // ƒ (b){ // console.log("延迟处理",a,b) // }
如上 delayHandle(111)
不像 directHandle(111,222)
直接打印值,而是先返回一个函数 f(b)
;111 也被临时保存了,delayHandle(111)(222)
,则得到相同的输出。这就是:延迟处理的思想。
另外补一句:
延迟处理是函数式编程的精华所在,在不能保证每个函数都是纯函数的前提下,在管道处理的最后,再进行处理,能最大程度的保证减少副作用。也就是 Monad 思想,此处不做展开。
言归正传,于是乎,我们借用闭包来实现最初版的柯里化:
// 两数相加 function addCurry(a){ return function(b){ console.log(a+b) } } addCurry(1)(2) // 三数相加 function addCurry(a){ return function(b){ return function(c){ console.log(a+b+c) } } } addCurry(1)(2)(3)
写两个闭包的过程,聪明的你一定就明白了,这样一直写下去,不就是递归吗?!
于是乎,我们知道,当参数是 n 个的时候,需要递归 n-1 次 return function
于是乎,addCurry 写法如下:
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)()
OK,至此,,大功告成!!
以上,用最简单的代码解释了 —— 为什么我说:柯里化 == 闭包+递归 ?
柯里化是一种思想,上面的 addCurry 可以说是最简单的一种实践。在函数式编程中,Curry 更是大放异彩,比如 compose(fn1)(fn2)(fn3)…(fnN)(args) 等等。
如果以后有人再问你柯里化,可以往这个方向上答。。。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
这篇文章主要介绍了js前端解决跨域的八种实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
JavaScript中移除onclick事件的方法是什么?在JavaScript中想要移除onclick事件,首先我们需要获取元素对象,然后元素对象.onclick=null语句就能实现了。文中的示例代码介绍得很详细,有需要的朋友可以参考,接下来就跟随小编一起了解看看吧。
这篇文章主要为大家介绍了javascript进阶篇深拷贝实现的四种方式详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
Vue3中有一对新增的api,provide和inject,熟悉Vue2的朋友应该明,这篇文章主要给大家介绍了关于vue3如何使用provide实现状态管理的相关资料,需要的朋友可以参考下
这篇文章主要为大家介绍了Vue编译器AST抽象语法树源码分析详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008