JavaScript学习(3):函数式编程
2013-07-07 20:06
435 查看
在这篇文章里,我们讨论函数式编程。
什么是函数式编程?根据百度百科的描述,“函数式编程是种编程典范,它将电脑运算视为函数的计算。函数编程语言最重要的基础是 λ 演算(lambda calculus)。而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。和过程化编程相比,函数式编程里,函数的计算可随时调用。”
可以看出,在函数式编程中,函数被看做是“一等公民”。JavaScript可以通过巧妙地函数组合来构建抽象,通过内嵌函数的方式,在软件开发的过程中,我们可以把更多的精力放在“函数要做什么”上,而不用太关心“函数如何做”的问题。
forEach函数包含两个参数,第一个参数是一个数组,第二个参数是一个函数,在forEach函数体内,会遍历数组的每一个元素,然后针对每一个元素调用func函数。
在调用forEach函数时,我们针对第二个参数,使用了匿名函数,它接受一个参数,这个参数其实就是数组中的元素。
从这个示例中,我们可以看到通过这种方式,可以明显简化对数组的操作。
reverse的作用是逆转传入函数的操作,在示例中,isNaN函数返回传入参数是否是NaN。
Reduce函数中参数的顺序是一个传统,我们可以将第一个参数作为匿名函数的方式传入。
下面是两个使用Reduce函数的示例,分别计算数组元素的和以及数组中0的个数:
Map函数的结构如下:
我们可以如下调用map方法:
这个示例将数组中的每个元素进行平方操作,然后输出。
对象中,属性的值不仅仅可以是集合属性,也可以是函数。上述示例使用这种方式对四则运算进行了封装。然后调用reduce方法去计算数组元素的和。
在这里,1是放在匿名函数中。我们还可以这样做,使用分布应用的方式在外函数和内嵌函数中分别保存部分参数。
分布应用的结构如下:
如果想要实现上面同样的功能,代码如下:
需要注意的是partial函数中在内嵌函数中如何将外函数和内嵌函数的参数进行整合,构成完整的参数列表。
以a=[1,2,3,4,0]为例,map函数会遍历数组中的每一个元素,当遍历到2时,参数的变化过程:
1. 外函数参数:1) ops["+"]; 2) 1。
2. 内嵌函数参数: 2
3. 完整参数:1,2
4. func.apply(null, realArgs): ops["+"](1,2)
就像这样:
上面示例中的isNotNaN也是这种情况。
什么是函数式编程?根据百度百科的描述,“函数式编程是种编程典范,它将电脑运算视为函数的计算。函数编程语言最重要的基础是 λ 演算(lambda calculus)。而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。和过程化编程相比,函数式编程里,函数的计算可随时调用。”
可以看出,在函数式编程中,函数被看做是“一等公民”。JavaScript可以通过巧妙地函数组合来构建抽象,通过内嵌函数的方式,在软件开发的过程中,我们可以把更多的精力放在“函数要做什么”上,而不用太关心“函数如何做”的问题。
高阶函数
可以操作其他函数的函数,被称为高阶函数。例如我们想对数组的每一个元素做某种操作,那么我们需要遍历整理数组,当操作发生改变时,我们还要重复编写遍历代码,利用高阶函数,可以简化这个过程。示例如下:function forEach(array,func){ for(var i = 0; i < array.length; i++){ func(array[i]); } } var a = ["a","b","c"]; forEach(a,function(obj){print(obj);}); forEach(a,function(obj){print(obj + 1);}); //输出结果 a b c a1 b1 c1
forEach函数包含两个参数,第一个参数是一个数组,第二个参数是一个函数,在forEach函数体内,会遍历数组的每一个元素,然后针对每一个元素调用func函数。
在调用forEach函数时,我们针对第二个参数,使用了匿名函数,它接受一个参数,这个参数其实就是数组中的元素。
从这个示例中,我们可以看到通过这种方式,可以明显简化对数组的操作。
修改函数
我们可以通过高阶函数很方便的修改已有函数的功能,示例如下:function reverse(func){ return function(value){ return !func(value); } } print(isNaN(NaN)); var isNotNaN = reverse(isNaN); print(isNotNaN(NaN)); //输出结果 true false
reverse的作用是逆转传入函数的操作,在示例中,isNaN函数返回传入参数是否是NaN。
规约函数
Reduce函数通过重复调用一个函数,将数组转换为单一的值。规约函数结构如下:function reduce(combine,base,array){ forEach(array, function(value){ base=combine(base,value); }); return base; }
Reduce函数中参数的顺序是一个传统,我们可以将第一个参数作为匿名函数的方式传入。
下面是两个使用Reduce函数的示例,分别计算数组元素的和以及数组中0的个数:
function countZeros(count,value){ return value == 0 ?(count+1) : count; } function add(sum,value){ return value+sum; } var a=[1,2,3,4,0]; print(reduce(add,0,a)); print(reduce(countZeros,0,a)); //输出结果 10 1
映射函数
Map函数会遍历数组,针对数组的每个元素,调用指定的操作,然后将操作得出的值存储到另外一个数组中,并返回新数组。Map函数的结构如下:
function map(func,array){ var result=[]; forEach(array, function(value){ result.push(func(value)); }); return result; }
我们可以如下调用map方法:
var a=[1,2,3,4,0]; print(map(function(value){ return value*value; }, a)); //输出结果 1,4,9,16,0
这个示例将数组中的每个元素进行平方操作,然后输出。
其他一些函数技巧
操作符函数
在JavaScript学习(1):基础中,我们使用内嵌函数实现了四则运算,接下来我们试着另外一种实现方式:var a=[1,2,3,4,0]; var ops={"+":function(x,y){return x+y;}, "-":function(x,y){return x-y;}, "*":function(x,y){return x*y;}, "/":function(x,y){return x/y;}, }; function operation(op, array){ if (op in ops){ return reduce(ops[op],0,array); } else{ throw new Error("invalid operation."); } } print(operation("+", a)); print(operation("^", a)); //输出结果 10
对象中,属性的值不仅仅可以是集合属性,也可以是函数。上述示例使用这种方式对四则运算进行了封装。然后调用reduce方法去计算数组元素的和。
分布应用
如果我们需要一个函数,但其中一个操作符的参数已经给定了,那应该如何处理?例如我们想对数组中的每个元素都做加1操作,使用map的方式实现:print(map(function(value){ return value + 1; },a));
在这里,1是放在匿名函数中。我们还可以这样做,使用分布应用的方式在外函数和内嵌函数中分别保存部分参数。
分布应用的结构如下:
function partial(func){ var knowArgs=arguments; return function(){ var realArgs=[]; for(var i = 1; i < knowArgs.length; i++){ realArgs.push(knowArgs[i]); } for(var i = 0; i < arguments.length; i++){ realArgs.push(arguments[i]); } return func.apply(null, realArgs); } }
如果想要实现上面同样的功能,代码如下:
print(map(partial(ops["+"], 1), a));
需要注意的是partial函数中在内嵌函数中如何将外函数和内嵌函数的参数进行整合,构成完整的参数列表。
以a=[1,2,3,4,0]为例,map函数会遍历数组中的每一个元素,当遍历到2时,参数的变化过程:
1. 外函数参数:1) ops["+"]; 2) 1。
2. 内嵌函数参数: 2
3. 完整参数:1,2
4. func.apply(null, realArgs): ops["+"](1,2)
函数组合
函数组合的含义是在调用函数A的过程中,它使用函数B来计算返回结果。就像这样:
function compose(f1,f2){ return function(){ return f1(f2.apply(null,realArgs)); } }
上面示例中的isNotNaN也是这种情况。
相关文章推荐
- JavaScript 学习笔记十二 函数式编程风格
- [学习笔记]JavaScript之函数式编程
- JavaScript 学习笔记十二 函数式编程风格
- Python学习笔记07_函数式编程
- JavaScript学习(读DOM编程艺术)
- JavaScript学习总结-技巧、有用函数、简洁方法、编程细节
- python学习 函数式编程
- Scala学习笔记--函数式编程
- python2.7学习笔记(7) ——函数式编程
- 关于学习JavaScript 的 高三编程 一些心得(二)
- 学习笔记:函数式编程
- javascript 之趣味 函数式编程
- JavaScript DOM 编程艺术 学习笔记(1)(从零学javascript)
- Python学习(二)——函数式编程
- JavaScript学习总结(九)——Javascript面向(基于)对象编程
- python学习——函数式编程
- 【python学习笔记】函数式编程:返回函数
- 【Python学习笔记】函数式编程:偏函数
- js 函数式编程学习笔记
- Web前端学习第十六天·fighting_JavaScript(DOM编程艺术5-6章)