javascript里的偏函数——本质函数式编程+闭包,返回函数
2016-11-25 17:52
776 查看
最终效果:
来自:http://lodashjs.com/docs/#_partialfunc-partials
除非你已经使用过其他的函数式编程,不然你可能对下面这两个概念很陌生:“偏函数应用”和“函数柯里化“。
话虽如此,但是假如你一旦理解了这两个概念,你就完全可以在自己的代码里使用他们。
但是我还是推荐你读一下这个第一部分。如果不需要,也可以跳过,直接看局部应用的章节。
我们首先看一个非常基础的例子:
尽管上面的例子是非常的简单,但是还是演示出了我们反复调用一个function的场景,并且每次传入的第一个参数都是相同的,在上面的代码里就是数字1
返回的函数,如果往里面传入参数调用,可以把传入的参数值和原来设的参数值,返回相加的结果。
上面的代码之所以可行,是因为JavaScript支持闭包的功能,由于闭包的存在,使得function可以访问到这个function外部的变量,甚至在调用这个function时的作用域的外层。
除此之外,在JavaScript里面,function是一等公民。正因为如此,function可以接受function作为参数,也可以返回function.
闭包和函数这个一等公名经常一起配合着工作:使得返回的function可以继续使用传入的参数。
上面的代码给我们提供了一些方便,我们可以不再使用add(1, 2),而直接使用addOne(2),但是实现这个并不是不需要付出代价的。
首先,实际做加法的逻辑在上面两个例子的代码中还是重复的,这样还是会有些问题。
其次,对每个类似于上面的加法场景,用这种方式去独立除不同的逻辑,我们将需要手工创建makeSomething的工厂function。
用这种方式,一个单独的工厂function能够被用来创建function绑定。
注意,原始的function被没有被更新,并且他们的行为也不会改变。他们很容易被调用。
上面这段代码,亮点不在于它可以将某个参数绑定到任意的function,并且这个参数作为绑定的function的第一个参数,它还能将方法绑定它自己身上作为第一个参数,因此创建了一个可绑定的function
想想这种情况:假如bindFirstArg能够将第一个参数绑定到一个function,但是这个function可以接受两个参数,比如传进去1和10,1用来加,10用来乘。
bindFirstArg可以接受两个2参数,假如第一个参数是它自己,也就是bindFirstArg可以用来绑定它自己。
看下面的例子:
var greet = function(greeting, name) { return greeting + ' ' + name; }; var sayHelloTo = _.partial(greet, 'hello'); sayHelloTo('fred'); // => 'hello fred'
来自:http://lodashjs.com/docs/#_partialfunc-partials
除非你已经使用过其他的函数式编程,不然你可能对下面这两个概念很陌生:“偏函数应用”和“函数柯里化“。
偏函数应用,英文是partial application,也可以译作“局部应用”、“部分应用”、“偏应用” 函数柯里化,英文是currying,也可以译作“局部套用”、“加里化”、“卡瑞化”
话虽如此,但是假如你一旦理解了这两个概念,你就完全可以在自己的代码里使用他们。
Functions
即使你已经很熟悉JavaScript的function, 知道function可以作为返回值,可以作为参数。但是我还是推荐你读一下这个第一部分。如果不需要,也可以跳过,直接看局部应用的章节。
我们首先看一个非常基础的例子:
function add(a, b) { return a + b; } add(1, 2); // 3 add(1, 3); // 4 add(1, 10); // 11 add(1, 9000); // 9001
尽管上面的例子是非常的简单,但是还是演示出了我们反复调用一个function的场景,并且每次传入的第一个参数都是相同的,在上面的代码里就是数字1
Functions返回Functions
我们也可以创建一个叫做makeAdder的function,这个function会返回另一个可以传入参数的function。(像这种可以用来创建其他function或object的function,一般会叫做工厂 - factories)返回的函数,如果往里面传入参数调用,可以把传入的参数值和原来设的参数值,返回相加的结果。
// More general function. function add(a, b) { return a + b; } add(1, 2); // 3 add(10, 3); // 13 // More specific function generator. function makeAdder(a) { return function(b) { return a + b; }; } // More specific functions. var addOne = makeAdder(1); addOne(2); // 3 addOne(3); // 4 var addTen = makeAdder(10); addTen(2); // 12 addTen(3); // 13
上面的代码之所以可行,是因为JavaScript支持闭包的功能,由于闭包的存在,使得function可以访问到这个function外部的变量,甚至在调用这个function时的作用域的外层。
除此之外,在JavaScript里面,function是一等公民。正因为如此,function可以接受function作为参数,也可以返回function.
闭包和函数这个一等公名经常一起配合着工作:使得返回的function可以继续使用传入的参数。
上面的代码给我们提供了一些方便,我们可以不再使用add(1, 2),而直接使用addOne(2),但是实现这个并不是不需要付出代价的。
首先,实际做加法的逻辑在上面两个例子的代码中还是重复的,这样还是会有些问题。
其次,对每个类似于上面的加法场景,用这种方式去独立除不同的逻辑,我们将需要手工创建makeSomething的工厂function。
Functions接受Functions
下面的逻辑步骤是创建一个更普遍的工厂function,不仅接受一个要绑定的参数,也会接受一个function,这个function里面包含了所有的核心逻辑。(传入到其他function的function,一般被成为回调函数-callbacks)用这种方式,一个单独的工厂function能够被用来创建function绑定。
注意,原始的function被没有被更新,并且他们的行为也不会改变。他们很容易被调用。
// Relatively flexible, more specific function generator. function bindFirstArg(fn, a) { return function(b) { return fn(a, b); }; } // More general functions. function add(a, b) { return a + b; } add(1, 2); // 3 function multiply(a, b) { return a * b; } multiply(10, 2); // 20 // More specific functions. var addOne = bindFirstArg(add, 1); addOne(2); // 3 addOne(3); // 4 addOne(10); // 11 addOne(9000); // 9001 var multiplyByTen = bindFirstArg(multiply, 10); multiplyByTen(2); // 20 multiplyByTen(3); // 30 multiplyByTen(10); // 100 multiplyByTen(9000); // 90000
上面这段代码,亮点不在于它可以将某个参数绑定到任意的function,并且这个参数作为绑定的function的第一个参数,它还能将方法绑定它自己身上作为第一个参数,因此创建了一个可绑定的function
想想这种情况:假如bindFirstArg能够将第一个参数绑定到一个function,但是这个function可以接受两个参数,比如传进去1和10,1用来加,10用来乘。
bindFirstArg可以接受两个2参数,假如第一个参数是它自己,也就是bindFirstArg可以用来绑定它自己。
看下面的例子:
// More specific function generator. var makeAdder = bindFirstArg(bindFirstArg, add); // More specific functions. var addOne = makeAdder(1); addOne(2); // 3 addOne(3); // 4 var addTen = makeAdder(10); addTen(2); // 12 addTen(3); // 13
相关文章推荐
- Javascript中的返回函数与闭包
- javascript中的返回函数与闭包
- Javascript 中的返回函数和闭包
- Python入门 第四天(函数式编程、map、reduce、filter、排序函数、函数返回函数、闭包、匿名函数lambda)
- (Javascript) 猴子也明白 之 闭包超级入门 4 函数返回函数
- JavaScript DOM 中setAttribute()的使用 以及点击鼠标返回函数的处理
- javascript基础之六(函数的闭包)
- javascript-函数进阶(闭包)
- JavaScript权威设计--命名空间,函数,闭包(简要学习笔记十二)
- javascript之函数作用域和闭包[function scope and closure]
- Python学习笔记(12) -- (关键词:返回函数/闭包)
- JavaScript 函数声明、函数定义、匿名函数和闭包的区别
- 返回函数和闭包
- 自我学习——javascript——闭包的本质
- 翻译连载 | JavaScript 轻量级函数式编程-第2章:函数基础 |《你不知道的JS》姊妹篇
- JavaScript的变量及函数(变量提升、嵌套作用域、条件语句、严格模式、IIFE、闭包、模块化、this、原型)
- JavaScript 函数闭包实现多个事件的监听
- 关于QT中evaluateJavaScript()函数返回值的处理问题
- Javascript基础——深入了解Javascript(函数返回值return、函数传参arguments、兼容各浏览器的单一行间样式、元素的插入删除split/shift/sort/pop)