你好,你可以这样理解,函数式编程它不修改状态,因此函数式编程只是返回新的值,不修改系统变量。函数式编程思想是把运算过程尽量写成一系列嵌套的函数调用。
它主要是通过闭包和高阶函数等来进行编程,属于面向过程编程,强调通过函数,而不是语句来编程。
在探讨柯里化之前,我们首先聊一聊很容易跟其混淆的另一个概念—— 偏函数(Partial Application) 。在维基百科中,对 Partial Application 的定义是这样的:
其含义是:在计算机科学中,局部应用(或偏函数应用)是指将 多个参数 固定在一个函数中,从而 产生另一个函数 的过程。
举个例子,假设我们是一个加工厂,用于生产梯形的零件,生产过程中我们要根据 订单来源方 给的一系列参数计算面积:
突然有一天,我们发现了一个问题:我们的大部分订单零件,都是高度为 28 的规格,此时面积函数调用经常是这个样子的:
此时,我们便可以 以第一个函数为模板 ,来创建 存储了固定值的新的计算函数 :
当然,这个示例中并没有以明显的 偏函数 的方式去呈现,我们可以让返回结果变成一个新的函数,因此我们可以加以改造:
也可以将其简化为:
这里,我们就可以将 trapezoidAreaByHeight15() 、 trapezoidAreaByHeight28() 和 trapezoidAreaByHeight33() 视为 trapezoidArea() 的偏函数。
偏函数 往往不能改变一个函数的行为,通常是根据一个已有函数而生成一个新的函数,这个新的函数具有已有函数的相同功能,区别在于在新的函数中有一些参数 已被固定 不会变更。偏函数的设计通常:
柯里化(Currying) 是以美国数理逻辑学家哈斯凯尔·科里(Haskell Curry)的名字命名的函数应用方式。 与偏函数很像的地方是:都可以缓存参数,都会返回一个新的函数,以提高程序中函数的适用性。 而不同点在于, 柯里化(Currying) 通常用于分解原函数式,将参数数量为 n 的一个函数,分解为参数数量为 1 的 n 个函数,并且支持连续调用。例如:
可见, 柯里化(Currying) 用于将多元任务分解成单一任务,每一个独立的任务都 缓存了上一次函数生成时传递的入参 ,并且让新生成的函数更简单、专注。上述演变也可以写作:
柯里化(Currying) 分解了函数设计过程,将运行的步骤拆分为每一个单一参数的 lambda 演算。这里例举一个在 JavaScript 中用于做强制类型判断的示例:
使用这一的方式构建的函数 checkType() 具备了高通用性,但适用性则略差。我们发现 每次的调用过程,使用者都需要编写参数 typeStr 表示的类型字符串 ,增加了函数的应用复杂度。此时作为设计者,就可以对该函数加以改造,使其生成多个具备高适用性的独立函数:
柯里化(Currying) 分解了函数设计过程,将运行的步骤拆分为每一个单一参数的 lambda 演算。我们可以通过递归的方式,来构造出一个可进行无限调用,并返回相同的累加函数的 柯里化函数 :
调用方式如:
以这样的方式,我们构建的参数是一个简单对象 nexter ,该对象至少包含一个 value 属性,用于描述本次累加的值。如果希望获取累加结果,则为 nexter 对象赋予函数属性 success 即可。结果会以实参的形式,传递给 success 函数用于传递通知。
Promise 对象无论是构造函数还是后续的链式调用中,都能看到 柯里化 设计的影子:接收单一参数,返回一个 Promise :
调用方式为:
首先要有一个概念:并不是一个语言支持函数,这个语言就可以叫做“函数式语言”。函数式语言中的函数(function),除了能被调用之外,还具有一些其他性质。有以下三点:1.
函数是运算元
2.
在函数内保存数据
3.
函数内的运算对函数外无副作用
一、函数是运算元
普通的函数调用时,可以抽象的理解为:函数就是一个运算符,传入的参数是运算元;
但当JavaScript中的函数作为另一个函数的参数使用时,是传递引用的,这个“传入参数”就可以被理解为是一个运算元。由此的结论是,(作为“传入参数”的)函数具有运算元的含义,“函数参数”与普通参数并没有什么不同。
二、在函数内保存数据
在命令式语言中,函数内部的私有变量(局部变量)是不能被保存的。从程序的执行方式上来讲,局部变量在栈上分配,在函数执行结束后,所占用的栈被释放。因此函数内的数据不可能被保存。
在JavaScript的函数中,函数内的私有变量可以被修改,而且当再次“进入”到该函数内部时,这个被修改的状态仍将持续。下面的例子说明了这个特性:
复制代码
代码如下:
var
set,get
function
MyFunc(){
var
value
=
100
function
set_value(v){
value
=
v
}
function
get_value(){
return
value
}
set
=
set_value
get
=
get_value
}
MyFunc()
console.log(get())
//100
set(300)
console.log(get())
//300