JavaScript学习(3):函数式编程
在这篇文章里,我们讨论函数式编程。
什么是函数式编程?根据百度百科的描述,“函数式编程是种编程典范,它将电脑运算视为函数的计算。函数编程语言最重要的基础是 λ 演算(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学习(3):函数式编程的更多相关文章
- 给 JavaScript 开发者讲讲函数式编程
本文译自:Functional Programming for JavaScript People 和大多数人一样,我在几个月前听到了很多关于函数式编程的东西,不过并没有更深入的了解.于我而言,可能只 ...
- JavaScript系列:函数式编程(开篇)
前言: 上一篇介绍了 函数回调,高阶函数以及函数柯里化等高级函数应用,同时,因为正在学习JavaScript·函数式编程,想整理一下函数式编程中,对于我们日常比较有用的部分. 为什么函数式编程很重要? ...
- [学习] 从 函数式编程 到 lambda演算 到 函数的本质 到 组合子逻辑
函数式编程 阮一峰 <函数式编程初探>,阮一峰是<黑客与画家>的译者. wiki <函数编程语言> 一本好书,<计算机程序的构造与解释>有讲到schem ...
- 大数据技术之_16_Scala学习_04_函数式编程-基础+面向对象编程-基础
第五章 函数式编程-基础5.1 函数式编程内容说明5.1.1 函数式编程内容5.1.2 函数式编程授课顺序5.2 函数式编程介绍5.2.1 几个概念的说明5.2.2 方法.函数.函数式编程和面向对象编 ...
- javascript - Underscore 与 函数式编程
<Javascript函数式编程 PDF> # csdn下载地址http://download.csdn.net/detail/tssxm/9713727 Underscore # git ...
- 通过代数,数字,欧几里得平面和分形讨论JavaScript中的函数式编程
本文是对函数式编程范式的系列文章从而拉开了与以下延续一个. 介绍 在JavaScript中,函数只是对象.因此,可以构造函数,作为参数传递,从函数返回或分配给变量.因此,JavaScript具有一流的 ...
- [置顶] Ruby,Scala和JavaScript中的函数式编程(一)
函数式编程(英语:Functional programming)或者函数程序设计,又称泛函编程,是一种编程范型,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象.函数编程语言最重要的 ...
- Scala学习笔记--函数式编程
一.定义 简单说,"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论. 它属于"结构化编程&qu ...
- Scala - 快速学习09 - 函数式编程:一些操作
1- 集合类(collection) 系统地区分了可变的和不可变的集合. scala.collection包中所有的集合类 可变集合(Mutable) 顾名思义,意味着可以修改,移除或者添加一个元素. ...
- Scala - 快速学习08 - 函数式编程:高阶函数
函数式编程的崛起 函数式编程中的“值不可变性”避免了对公共的可变状态进行同步访问控制的复杂问题,能够较好满足分布式并行编程的需求,适应大数据时代的到来. 函数是第一等公民 可以作为实参传递给另外一个函 ...
随机推荐
- css基础总结一
最近在弄一个简单管理系统的前端,所以打算将做项目的一些个人感想以及总结简单罗列下,当然,主要针对前端的基础部分以及一些常用的前端个人简单技巧总结.主要分为js部分和css部分,下面是css的基础部分总 ...
- javascript类型系统——undefined和null
× 目录 [1]原因 [2]undefined [3]null 前面的话 一般的程序语言,表示空的只有null,但javascript的设计者Brendan Eich却设计了一个undefined,这 ...
- 【大数据】Linux下Storm(0.9版本以上)的环境配置和小Demo
一.引言: 在storm发布到0.9.x以后,配置storm将会变得简单很多,也就是只需要配置zookeeper和storm即可,而不再需要配置zeromq和jzmq,由于网上面的storm配置绝大部 ...
- 大M法(Big M Method)
前面一篇讲的单纯形方法的实现,但程序输入的必须是已经有初始基本可行解的单纯形表. 但实际问题中很少有现成的基本可行解,比如以下这个问题: min f(x) = –3x1 +x2 + x3 s.t. x ...
- 各大IT公司校园招聘程序猿笔试、面试题集锦
转自:http://blog.csdn.net/hackbuteer1/article/details/7959921#t4 百度一面 1.给定一个字符串比如“abcdef”,要求写个函数编程“def ...
- JS弹出框插件zDialog再次封装
zDialog插件网址:http://www.jq22.com/jquery-info2426 再次封装zDialog的代码: (function ($) { $.extend({ iDialog: ...
- easyui的window插件再次封装
easyui的window插件再次封装 说明:该插件弹出的弹出框在最顶层的页面中,而不是在当前页面所在的iframe中,它的可拖动范围是整个浏览器窗口:所以不能用JS的parent对象获取弹出它的父页 ...
- 【WebService】WebService的创建和使用——文件名称生成器
简介 之前做过一个文件名称生成器,通过Webservice读取XML文件并将其通过Json传到客户端中的combobx,用户通过combobox选择要生成文件的名称模板,点击生成则会产生一个文件名称并 ...
- 在WCF数据访问中使用缓存提高Winform字段中文显示速度
在我们开发基于WCF访问方式的Winform程序的时候,一般情况下需要对界面显示的字段进行中文显示的解析.如果是硬编码进行中文显示,那么除了不方便调整及代码臃肿外,性能上没有什么问题,但是不建议这样处 ...
- iOS——使用StroryBoard页面跳转及传值
之前在网上搜iOS的页面跳转大多都是按回以前的那种xib的形式,但鄙人是使用storyboard的.这篇就只介绍利用storyboard进行页面跳转与传值. 新建页面 iOS的程序也是使用了MVC的思 ...