- 浏览: 452278 次
- 性别:
- 来自: 西安
文章分类
最新评论
-
进退取舍:
谢谢,这个用上了!!
Java 一个线程池的示例 -
pb_water:
感谢楼主,打算买楼主的书,支持一下,楼主功德无量
JavaScript内核系列第0版整理稿下载 -
lancezhcj:
有图会直观的多呢,再摸索摸索
有限自动机与建模 -
hsmsyy:
这里应该是原创了吧,楼主我觉得闭包的作用:实现面向对象。有待商 ...
JavaScript内核系列 第7章 闭包 -
wll52:
在应用退出之前,需要释放连接 con.disconnect() ...
使用smack与GTalk通信
前言
Javascript,有人称其为C+LISP,C只怕是尽人皆知,但是一直活跃在人工智能领域的另一个古老而优美的语言LISP,掌握的恐怕不是很多.这个倒不是因为这个语言太难或者用途不广泛,而是大多数人在接受计算机语言启蒙的时候都走的是图灵机模式,而LISP,做为一种函数式编程语言,是另一个体系:lambda演算体系.这个体系的运算能力跟图灵机的运算能力是相当的。
所以Javascript本身是一种很自由的,支持函数式编程的一个神奇的语言,在WEB中的应用只是它的以个小小的部分。脚本可以用来脚本化很多 东西,最主要的应用是在UI层面,很灵活(这也是Javascript用来脚本化HTML的一个重要原因)。我们这里要说的是一个100%java实现的 javascript引擎rhino,当然重点不是引擎本身,而是在其上解释JavaScript的函数式编程。(rhino可以在此处 http://www.mozilla.org/rhino/找到)。
函数式编程概览
我们先看几个例子,从感官上对其有一个了解,看一个幂计算函数,用命令式语言书写(命令式语言如C,Java等),大概就是下面这个样子:
if(n == 0){return 1;}
else{
return expt(b, n-1)*b;//正常的递归调用
}
}
再看看函数式编程的写法:
if(n == 0){
return 1;
}else{
return mul(expt(b, dec(n)), b);//所有操作均为函数
}
}
可以很明显的看到,有一大堆的括号,没有操作符(如+-*/等),这是因为,操作符在函数式编程中被认为是函数,与其他函数(数学函数,串处理函数等)的地位是同等的,当然这个不是最主要的,在函数式编程中最主要的是函数可以做为一个基本类型被返回,这一点时命令式语言无法完成的。
比如,定义一个函数,输入两个参数,计算这两个数的平方和:
你可以将这个函数赋值给一个变量,如下:
然后,最神奇的是,下边这样:
好了,简单的概述就此为止,下面我们看一些更高级的主题:高阶函数。
高阶函数
事实上,所有的有关函数式编程的文章必须要涉及到这个主题,这是因为,在命令式语言中,我们的抽象是根据"类"(这正是现在流行的OO的基本思想)来进行的,但是,在函数式编程中,没有办法表示类的概念,但是同样可以进行高级的抽象方式,使得一个函数更加泛化,可以被"实例化"成其他的函数,这个就是高阶函数。
来看个例子,我们有这样几种求和运算:
function inc(x){ return x + 1; }
function identity(x){ return x; }
if(a > b){
return 0;
}else{
return intSum(inc(a) , b) + identity(a);
}
}
function cubeSum(a, b){
function inc(x){ return x + 1; }
function cube(x){ return x * x * x; }
if(a > b){
return 0;
}else{
return cubeSum(inc(a) , b) + cube(a);
}
}
function piSum(a, b){
function piTerm(x){ return 1/((x+2)*x); }
function piNext(x){ return x+4; }
if(a > b){
return 0;
}else{
return piSum(piNext(a) , b) + piTerm(a);
}
}
第一个函数用来计算从a-b的数的总和,步长为1,第二个函数计算a-b的立方和,步长为1,第三个函数计算a-b的一个方程的和(将a-b中的每一个数带入此方程进行计算),步长为4.
从函数的形式以及函数的作用来看,这三个函数有很大的共性,所以我们考虑是否可以将这些共性抽取出来,将每次计算的步长和方程传入,进行求和计算??答案当然是肯定的,下面我们来抽象:
- 定义下一个参与计算的数(通过步长函数的定义)
- 定义求什么的和(函数体的定义)
有了这两个函数,我们就可以计算任意的方程,指定区间的求和操作,将上述的两个函数做为参数传入,输出即为运算结果:
if(a > b){
return 0;
}else{
return sum(term, next(a), next, b)+term(a);
}
}
这个函数需要四个参数,一个是关于计算子的定义term,一个是步长函数next,另外两个即为区间的两个端点a,b,这样我们可以重新定义上述的三个函数如下:
function inc(x){return x + 1;}
function identity(x){return x;}
return sum(identity, a, inc, b);//调用通用的抽象接口
}
function cubeSum(a, b){
function inc(x){return x + 1;}
function cube(x){return x * x * x;}
return sum(cube, a, inc, b);//调用通用的抽象接口
}
function piSum(a, b){
function piTerm(x){ return 1/((x+2)*x); }
function piNext(x){ return x+4; }
return sum(piTerm, a, piNext, b);//调用通用的抽象接口
}
高阶函数提供了更高级的抽象,从而使得程序的结构更加清晰。下面我们再看看函数式语言的优雅的代码,匿名函数:
匿名函数
我们先对一些简单的操作进行简单的包装(如四则运算,boolean运算等操作):
function add(a, b){ return a+b; }
function sub(a, b){ return a-b; }
function mul(a, b){ return a*b; }
function div(a, b){ return a/b; }
function rem(a, b){ return a%b; }
function inc(x){ return x + 1; }
function dec(x){ return x - 1; }
function equal(a, b){ return a==b; }
function great(a, b){ return a>b; }
function less(a, b){ return a<b; }
function negative(x){ return x<0; }
function positive(x){ return x>0; }
然后,在这些共用的语法糖(并非严格意义上的语法糖,但是它们的确是!)的基础上,做一些简单的函数定义:
function factorial(n){
if(equal(n, 1)){
return 1;
}else{
return mul(n, factorial(dec(n)));
}
}
//对上边的函数的另一种定义方式
/*
* product <- counter * product
* counter <- counter + 1
* */
function factorial(n){
function fact_iter(product, counter, max){
if(counter > max){
return product;
}else{
fact_iter(mul(counter, product), inc(counter), max);
}
}
return fact_iter(1, 1, n);
}
function expt(b, n){
if(n == 0){
return 1;
}else{
return mul(expt(b, dec(n)), b);
}
}
function gcd(a, b){
if(b == 0){
return a;
}else{
return gcd(b, rem(a, b));
}
}
function search(fx, neg, pos){
function closeEnough(x, y){return less( abs( sub(x, y) ), 0.001)};
var mid = (function(x, y){return div( add(x, y), 2);})(neg, pos);
if(closeEnough(neg, pos)){
return mid;
}else{
var test = fx(mid);
if(positive(test)){
return search(fx, neg, mid);
}else if(negative(test)){
return search(fx, mid, pos);
}else{
return mid;
}
}
}
function halfIntervalMethod(fx, a, b){
var av = fx(a);
var bv = fx(b);
if(negative(av) && positive(bv)){
return search(fx, a, b);
}else if(negative(bv) && positive(av)){
return search(fx, b, a);
}else{
print("error happend!!");
}
}
//计算一个函数的不动点
function fixedPoint(fx, first){
var tolerance = 0.00001;
function closeEnough(x, y){return less( abs( sub(x, y) ), tolerance)};
function Try(guess){
var next = fx(guess);
//print(next+" "+guess);
if(closeEnough(guess, next)){
return next;
}else{
return Try(next);
}
};
return Try(first);
}
// magic function sqrt, a little hard to read, hah?
function sqrt(x){
return fixedPoint(
function(y){
return function(a, b){ return div(add(a, b), 2);}(y, div(x, y));
},
1.0);
}
如果上边的几个都可以完全理解,那么常识看看最下面的这个计算一个函数的平方根的函数sqrt(x),你会发现这个函数很有意思,其中的那个匿名函数最有意思,我写了个测试函数:
//计算两个数的平方和的匿名函数
var y = (function(x, y){ return add( expt(x, 2), expt(y, 2) ); })(3, 4);
print(y);
print(halfIntervalMethod(sin, 2.0, 4.0));
print(halfIntervalMethod(function(x){return expt(x, 3) - mul(2, x) - 3;}, 1.0, 2.0));//x^3-2x-3
print(fixedPoint(cos, 1.0));//cos的不动点
print(fixedPoint(function(x){return add( sin(x), cos(x)); }, 1.0));
print(sqrt(100));
}
运行结果如下:
25
3.14111328125
1.89306640625
0.7390822985224024
1.2587315962971173
10
js>
好了,关于函数式编程就大概介绍到这里,下面简单说说这个rhino包
关于Rhino
rhino是一个纯java的javascript引擎的实现,下载之后,将js.jar加入classpath,然后在命令行中输入:
java org.mozilla.javascript.tools.shell.Main
即可启动,可以使用load(path/of/script)来加载,加载完成后即可使用脚本中定义的函数,非常方便,当然DOM中的一切是不能用的,比如alert什么的,但是javascript不只是用来脚本化WEB页面的。可以使用print进行打印,使用quit()退出等,下面做一个关于rhino的例子:
name:"abruzzi",
password:"123456",
address:{
zip:"612345",
street:"west HuangQuan road"
},
getName: function(){return this.name;},
getPassword: function(){return this.password;},
getAddress: function(){ return this.address.zip+"\n"+this.address.street;}
}
Rhino 1.7 release 2 2009 03 22
js> load('~/development/myLib/HighOrderFunc/json.js')
js> user
[object Object]
js> user.getName()
abruzzi
js> user.getPassword()
123456
js> user.getAddress()
612345
west HuangQuan road
js>
在rhino的发行包中有一些特别有趣的例子,大家不妨自己动手做一下,看看效果,同时体会一下函数式编程的优美,简介。
发表评论
-
JavaScript内核系列 第15章 服务器端的JavaScript
2012-02-12 21:39 2324第15章已经在icodeit上发布,这一章分为上/下两篇,请朋 ... -
使用vim开发python及graphviz绘图
2011-12-23 14:49 6456基本需求 使用vim中的autocmd命令可以很容易的将正在 ... -
Java脚本技术应用实例
2011-01-22 11:24 4266前言 一直以来都很喜欢可以自由扩展的软件,这一点应该已经在很 ... -
可编程计算器(phoc)的设计与实现
2011-01-17 11:34 1981前言 借助JavaScript脚本 ... -
C和指针
2009-05-21 23:15 1116前言 指针是C的灵魂,正是指针使得C存在了这么多年,而且将长 ... -
C和指针(续)
2009-05-25 23:41 1358前言 上一篇《C和指针》可能对关于C和指针的有些内容没有说透 ... -
有限自动机与建模
2009-06-06 10:48 1785前言 在学校学程序设计语言的时候,能接触到的所有例子没有一个 ... -
事件和监听器
2009-06-21 22:06 1436前言 事件监听器是经 ... -
基于总线的消息服务(BBMS)的设计与实现
2009-07-25 22:19 1364前言 异步事件的通知机制在比较有规模的软件设计中必然会有涉及 ... -
JavaScript内核系列 第9章 函数式的Javascript
2010-05-13 19:20 3785第九章 函数式的Javascript 要说Ja ... -
JavaScript内核系列 第8章 面向对象的JavaScript(下)
2010-05-06 09:40 3670接上篇:JavaScript内核系列 第8章 面向对象的Jav ... -
JavaScript内核系列 第8章 面向对象的JavaScript(上)
2010-05-06 09:26 2903第八章 面向对象的 Javascript ... -
JavaScript内核系列 第7章 闭包
2010-05-04 08:48 3873第七章 闭包 闭包向来给包括JavaScript程序 ... -
JavaScript内核系列 第6章 正则表达式
2010-04-27 19:44 4048第六章 正则表达式 正则表达式是对字符串的结构 ... -
JavaScript内核系列 第5章 数组
2010-04-24 15:17 4529第五章 数组 JavaScript的数组也是一个比较 ... -
Swing小应用(Todo-List)之三
2010-04-22 20:47 2135前言 去年9月份开发的那个小工具sTodo,只是做到了能用, ... -
JavaScript内核系列 第4章 函数
2010-04-18 17:31 5093第四章 函数 函数,在C语言之类的过程式语言中 ... -
JavaScript内核系列 第3章 对象与JSON
2010-04-12 09:12 6131第三章 对象与JSON JavaScript对象与传 ... -
JavaScript内核系列 第2章 基本概念
2010-04-03 19:44 5683第二章 基本概念 ... -
JavaScript内核系列 第1章 前言及概述
2010-04-01 23:15 9968前言 从2006年第一次接触JavaScript至今,算来也 ...
相关推荐
通过事件监听器,开发者可以设置在特定事件发生时执行的代码块,实现响应式编程。事件处理在创建交互丰富的网页和应用中起着至关重要的作用。 此外,书中可能还会涉及JavaScript的基本语法,如变量声明、数据类型...
Operators是函数式编程与事件处理的结合体,它提供了一系列组合、变换、过滤或应用逻辑等操作的机制。常见 Operators包括map、filter、concat、flatMap等,它们可以用于处理数据序列并执行复杂的操作。 Scheduler...
在压缩包文件中,"Javascript手册.chm"可能是一份关于JavaScript的参考手册,包含了语言的基本语法、对象、函数和API等内容,对学习和理解JavaScript编程非常有帮助。"飞翔下载说明.txt"和"安装必看.txt"可能是下载...
在本文中,我们将深入探讨JavaScript编辑器的重要特性、使用方法以及它如何帮助开发者进行高效的JavaScript编程。 首先,JavaScript是Web开发的核心语言,用于实现网页的动态交互和功能。JavaScript Editor作为专门...
8. **响应式设计**:为了适应不同设备的屏幕尺寸,JavaScript可以用于检测窗口大小并调整游戏布局,确保游戏在手机、平板电脑和桌面电脑上都能良好运行。 通过这个项目,开发者不仅可以学习到JavaScript的基本语法...
JavaScript游戏是一种利用JavaScript编程语言创建的交互式娱乐应用。JavaScript是一种广泛用于网页和网络应用的轻量级脚本语言,它允许开发者在用户的浏览器上直接运行代码,无需服务器的额外支持。JavaScript游戏...
此外,书中还包含了大量的函数高级用法的讲解,帮助读者提升对函数式编程的理解。 - **学习建议**:这本书适合那些希望进一步提升自己的JavaScript编程水平并优化代码结构的开发者。通过反复阅读和实践书中的例子,...
JavaScript,作为全球最广泛使用的编程语言之一,是创建交互式网页和应用程序的关键工具。"JavaScript实例大全"这个压缩包文件,显然提供了一系列丰富的代码示例,帮助开发者掌握和运用JavaScript的各种功能。以下将...
本示例中,"图片在窗体间移动效果(HTML+JavaScript)"是一个使用这两种技术实现的交互式功能,让图片在网页的不同区域之间平滑地移动,营造出一种动态视觉效果。这个效果可以通过编程方式实现,无需复杂的动画库,...
对于初学者来说,阅读和理解他人代码,以及使用调试工具(如浏览器的开发者工具)来查看运行结果和错误,是提高编程能力的有效方法。在实践中,可以尝试修改“test.html”中的代码,观察不同输入对输出的影响,加深...
JavaScript绘图技术是一种在网页上实现动态可视化的重要手段,它允许开发者通过编程方式创建各种复杂的图形,包括统计图。在Web开发中,JavaScript绘图库如D3.js、Chart.js、ECharts等提供了丰富的功能,使得即使...
4. **函数式编程(Functional Programming)**:JavaScript支持多种函数式编程概念,如高阶函数、纯函数、map、reduce、filter等。这部分可能介绍如何使用这些工具进行更高效、可维护的编程。 5. **原型和继承...
JavaScript特效代码大全是一份集合了各种常见JavaScript编程技巧和效果的资源库,旨在帮助开发者们快速实现网页中的动态效果。JavaScript作为一种广泛应用于客户端Web开发的脚本语言,它赋予了网页交互性和动态性,...
通过深入学习这些知识点,你可以掌握Java开发的基础和高级技能,进一步提升在Web开发、数据库交互、函数式编程等多个领域的专业能力。在实践中不断探索,将理论知识与实际项目相结合,是成为专业IT人士的关键步骤。
- 函数:`function`关键字用于定义函数,它们可以接收参数并返回值。 2. **DOM概念** - DOM树:HTML或XML文档被解析成一棵节点树,其中每个元素、属性和文本都是一个节点。 - Document对象:整个DOM树的根节点,...
13. **面向对象编程**:理解JavaScript的面向对象特性,包括构造函数、原型链和继承。 14. **性能优化**:学习如何提高JavaScript代码的运行效率,如避免全局查找、减少DOM操作等。 15. **错误处理**:学习如何...
JavaScript,作为全球最广泛使用的编程语言之一,是创建交互式网页和应用程序的关键工具。"经典封装"这个主题在JavaScript中通常指的是将代码组织成可重用的模块或对象,以便提高代码的清晰度、可维护性和性能。在这...
- 在React中应用函数式编程思想,如使用map、filter、reduce等数组方法操作数据。 5. **最佳实践**: - 组件设计原则:如何编写可复用、可测试、易于维护的组件。 - 错误边界:使用ErrorBoundary捕获和处理组件...
JavaScript和jQuery是Web开发中的两个重要工具,它们在创建交互式和动态网页方面发挥着关键作用。本资源“精通JavaScript+jQuery电子书+源码-部分2”是针对这两个技术的深入学习材料,旨在帮助开发者进一步提升技能...