上一篇文章引见了javascript
函数式编程中curry
(柯里化)的完成,固然谁人柯里化是有限参数的柯里化,等有机会在补上无穷参数的那一种柯里化,此次主要说的是javascript
函数式编程中别的一个很主要的函数compose
,compose
函数的作用就是组合函数的,将函数串连起来实行,将多个函数组合起来,一个函数的输出效果是另一个函数的输入参数,一旦第一个函数最先实行,就会像多米诺骨牌一样推导实行了。
简介
比方有如许的需求,要输入一个名字,这个名字有由firstName
,lastName
组合而成,然后把这个名字悉数变成大写输出来,比方输入jack
,smith
我们就要打印出来,‘HELLO,JACK SMITH’
。
我们斟酌用函数组合的要领来处置惩罚这个题目,须要两个函数greeting
, toUpper
var greeting = (firstName, lastName) => 'hello, ' + firstName + ' ' + lastName
var toUpper = str => str.toUpperCase()
var fn = compose(toUpper, greeting)
console.log(fn('jack', 'smith'))
// ‘HELLO,JACK SMITH’
这就是compose大抵的运用,总结下来要注意的有以下几点
compose
的参数是函数,返回的也是一个函数因为除了第一个函数的吸收参数,其他函数的吸收参数都是上一个函数的返回值,所以初始函数的参数是
多元
的,而其他函数的吸收值是一元
的compsoe
函数能够吸收恣意的参数,一切的参数都是函数,且实行方向是自右向左
的,初始函数肯定放到参数的最右面
晓得这三点后,就很轻易的剖析出上个例子的实行历程了,实行fn('jack', 'smith')
的时刻,初始函数为greeting
,实行效果作为参数传递给toUpper
,再实行toUpper
,得出末了的效果,compose的优点我简朴提一下,假如还想再加一个处置惩罚函数,不须要修正fn
,只须要在实行一个compose
,比方我们再想加一个trim
,只须要如许做
var trim = str => str.trim()
var newFn = compose(trim, fn)
console.log(newFn('jack', 'smith'))
就能够了,能够看出不管保护和扩大都非常的轻易。
完成
例子剖析完了,本着究其基础的准绳,照样要探讨与一下compose
究竟是怎样完成的,起首诠释引见一下我是怎样完成的,然后再寻找一下,javascript
函数式编程的两大类库,lodash.js
和ramda.js
是怎样完成的,个中ramda.js
完成的历程非常函数式。
我的完成
我的思绪是,既然函数像多米诺骨牌式的实行,我起首就想到了递归,下面就一步一步的完成这个compose
,起首,compose
返回一个函数,为了纪录递归的实行情况,还要纪录参数的长度len
,还要给返回的函数增加一个名字f1
。
var compose = function(...args) {
var len = args.length
return function f1() {
}
}
函数体内里要做的事变就是不停的实行args
中的函数,将上一个函数的实行效果作为下一个实行函数的输入参数,须要一个游标count
来纪录args
函数列表的实行情况。
var compose = function(...args) {
var len = args.length
var count = len - 1
var result
return function f1(...args1) {
result = args[count].apply(this, args1)
count--
return f1.call(null, result)
}
}
这个就是思绪,固然如许是不可的,没有退出前提,递归的退出前提就是末了一个函数实行完的时刻,也就是count
为0
的时刻,这时刻,有一点要注意,递归退出的时刻,count
游标肯定要回归初始状况,末了补充一下代码
var compose = function(...args) {
var len = args.length
var count = len - 1
var result
return function f1(...args1) {
result = args[count].apply(this, args1)
if (count <= 0) {
count = len - 1
return result
} else {
count--
return f1.call(null, result)
}
}
}
如许就完成了这个compose
函数。厥后我发明递归这个完全能够运用迭代来完成,运用while
函数看起来更轻易邃晓,实在lodash.js
就是这么完成的。
lodash
完成
lodash
的思绪同上,不过是用迭代完成的,我就把它的源代码贴过来看一下
var flow = function(funcs) {
var length = funcs.length
var index = length
while (index--) {
if (typeof funcs[index] !== 'function') {
throw new TypeError('Expected a function');
}
}
return function(...args) {
var index = 0
var result = length ? funcs[index].apply(this, args) : args[0]
while (++index < length) {
result = funcs[index].call(this, result)
}
return result
}
}
var flowRight = function(funcs) {
return flow(funcs.reverse())
}
能够看出,lodash
的原本完成是从左到右
的,但也供应了从右到左
的flowRight
,还多了一层函数的校验,而且吸收的是数组
,不是参数序列
,而且从这行var result = length ? funcs[index].apply(this, args) : args[0]
能够看出许可数组为空,能够看出照样非常严谨的。我写的就缺乏这类严谨的非常处置惩罚。
结论
此次主要引见了函数式编程中的compose
函数的道理和完成要领,因为篇幅缘由,我把盘算剖析的ramda.js
源码完成放到下一篇来引见,能够说ramda.js
完成的compose
越发函数式,须要零丁好好剖析。