简介
函数式编程语言在学术领域已经存在相当长一段时间了,但是从历史上看,它们没有丰富的工具和库可供使用。随着 .NET 平台上的
Haskell 的出现,函数式编程变得更加流行。一些传统的编程语言,例如 C++ 和
JavaScript,引入了由函数式编程提供的一些构造和特性。在许多情况下,JavaScript
的重复代码导致了一些拙劣的编码。如果使用函数式编程,就可以避免这些问题。此外,可以利用函数式编程风格编写更加优美的回调。
 |
函数式编程
函数式编程只描述在程序输入上执行的操作,不必使用临时变量保存中间结果。重点是捕捉 “是什么以及为什么”,而不是 “如何做”。与将重点放在执行连续命令上的过程性编程相比,函数式编程的重点是函数的定义而不是状态机(state machine)的实现。
大型知识管理系统应用程序从使用函数式编程风格上受益颇多,因为函数式编程简化了开发。
|
|
因为函数式编程采用了完全不同的组织程序的方式,所以那些习惯于采用命令式范例的程序员可能会发现函数式编程有点难学。在这篇文章中,您将了解一些关于如何采用函数式风格,用 JavaScript 编写良好的、优美的代码的示例。我将讨论:
-
函数式编程概念
,包括匿名函数、调用函数的不同方法,以及将函数作为参数传递给其他函数的方式。
-
函数式概念的运用
,采用的示例包括:扩展数组排序;动态 HTML 生成的优美代码;系列函数的应用。
函数式编程概念
在那些通过描述 “如何做” 指定解决问题的方法的语言中,许多开发人员都知道如何进行编码。例如,要编写一个计算阶乘的函数,我可以编写一个循环来描述程序,或者使用递归来查找所有数字的乘积。在这两种情况下,计算的过程都在程序中进行了详细说明。清单 1
显示了一个计算阶乘的可能使用的 C 代码。
清单 1. 过程风格的阶乘
int factorial (int n)
{
if (n <= 0)
return 1;
else
return n * factorial (n-1);
}
|
这类语言也叫做过程性
编程语言,因为它们定义了解决问题的过程。函数式编程与这个原理有显著不同。在函数式编程中,需要描述问题 “是什么”。 函数式编程语言又叫做声明性
语言。同样的计算阶乘的程序可以写成所有到 n
的数字的乘积。计算阶乘的典型函数式程序看起来如 清单 2
中的示例所示。
清单 2. 函数式风格的阶乘
factorial n, where n <= 0 := 1
factorial n := foldr * 1 take n [1..]
|
第二个语句指明要得到从 1 开始的前 n
个数字的列表(take n [1..]
),然后找出它们的乘积,1 为基元。这个定义与前面的示例不同,没有循环或递归。它就像阶乘函数的算术定义。一旦了解了库函数(take
和 foldr
)和标记(list notation [ ]
)的意义,编写代码就很容易,而且可读性也很好。
 |
只用三行 Miranda 代码就可以编写例程,根据参数,使用广度优先或深度优先遍历处理 n 叉树的每个节点,而且元素可以是任何通用类型。
|
|
从
历史上看,函数式编程语言不太流行有各种原因。但是最近,有些函数式编程语言正在进入计算机行业。其中一个例子就是 .NET 平台上的
Haskell。其他情况下,现有的一些语言借用了函数式编程语言中的一些概念。一些 C++ 实现中的迭代器和 continuation,以及
JavaScript 中提供的一些函数式构造(functional
construct),就是这种借用的示例。但是,通过借用函数式构造,总的语言编程范例并没有发生变化。JavaScript
并没因为函数式构造的添加就变成了函数式编程语言。
我现在要讨论 JavaScript 中的函数式构造的各种美妙之处,以及在日常编码和工作中使用它们的方式。我们将从一些基本功能开始,然后用它们查看一些更有趣的应用。
匿名函数
在 JavaScript 中,可以编写匿名函数或没有名称的函数。为什么需要这样的函数?请继续往下读,但首先我们将学习如何编写这样一个函数。如果拥有以下 JavaScript 函数:
清单 3. 典型的函数
function sum(x,y,z) {
return (x+y+z);
}
|
然后对应的匿名函数看起来应当如下所示:
清单 4. 匿名函数
function(x,y,z) {
return (x+y+z);
}
|
要使用它,则需要编写以下代码:
清单 5. 应用匿名函数
var sum = function(x,y,z) {
return (x+y+z);
}(1,2,3);
alert(sum);
|
使用函数作为值
也可以将函数作为值使用。还可以拥有一些所赋值是函数的变量。在最后一个示例中,还可以执行以下操作:
清单 6. 使用函数赋值
var sum = function(x,y,z) {
return (x+y+z);
}
alert(sum(1,2,3));
|
在上面 清单 6
的示例中,为变量 sum 赋的值是函数定义本身。这样,sum 就成了一个函数,可以在任何地方调用。
调用函数的不同方法
JavaScript 允许用两种方式调用函数,如清单 7
和 8
所示。
清单 7. 典型的函数应用
或
清单 8. 用函数作为表达式
(alert) (“Hello, World!");
|
所以也可以编写以下代码:
清单 9. 定义函数之后就可以立即使用它
( function(x,y,z) { return (x+y+z) } ) (1, 2, 3);
|
可以在括号中编写函数表达式,然后传递给参数,对参数进行运算。虽然在 清单 8
的示例中,有直接包含在括号中的函数名称,但是按 清单 9
中所示方式使用它时,就不是这样了。
将函数作为参数传递给其他函数
也可以将函数作为参数传递给其他函数。虽然这不是什么新概念,但是在后续的示例中大量的使用了这个概念。可以传递函数参数,如 清单 10
所示。
清单 10. 将函数作为参数传递,并应用该函数
var passFunAndApply = function (fn,x,y,z) { return fn(x,y,z); };
var sum = function(x,y,z) {
return x+y+z;
};
alert( passFunAndApply(sum,3,4,5) ); // 12
|
执行最后一个 alert 语句输出了一个大小为 12 的值。
使用函数式概念
前一节介绍了一些使用函数式风格的编程概念。所给的示例并没有包含所有的概念,它们在重要性方面也没有先后顺序,只是一些与这个讨论有关的概念而已。下面对 JavaScript 中的函数式风格作一快速总结:
- 函数并不总是需要名称。
- 函数可以像其他值一样分配给变量。
- 函数表达式可以编写并放在括号中,留待以后应用。
- 函数可以作为参数传递给其他函数。
这一节将介绍一些有效使用这些概念编写优美的 JavaScript 代码的示例。(使用 JavaScript 函数式风格,可以做许多超出这个讨论范围的事。)
扩展数组排序
先来编写一个排序方法,可以根据数组元素的日期对数据进行排序。用 JavaScript 编写这个方法非常简单。数据对象的排序方法接受一个可选参数,这个可选参数就是比较函数。在这里,需要使用 清单 11
中的比较函数。
清单 11. 比较函数
function (x,y) {
return x.date – y.date;
}
|
要得到需要的函数,请使用 清单 12
的示例。
清单 12. 排序函数的扩展
arr.sort( function (x,y) { return x.date – y.date; } );
|
其中 arr
是类型数组对象。排序函数会根据 arr
数组中对象的日期对所有对象进行排序。比较函数和它的定义一起被传递给排序函数,以完成排序操作。使用这个函数:
- 每个 JavaScript 对象都有一个 date 属性。
- JavaScript 的数组类型的排序函数接受可选参数,可选参数是用来排序的比较函数。这与 C 库中的
qsort
函数类似。
动态生成 HTML 的优美代码
在这个示例中,将看到如何编写优美的代码,从数组动态地生成 HTML。可以根据从数据中得到的值生成表格。或者,也可以用数组的内容生成排序和未排序的列表。也可以生成垂直或水平的菜单项目。
清单 13
中的代码风格通常被用来从数组生成动态 HTML。
清单 13. 生成动态 HTML 的普通代码
var str=' ';
for (var i=0;i<arr.length;i++) {
var element=arr[i];
str+=... HTML generation code...
}
document.write(str);
|
可以用 清单 14
的代码替换这个代码。
清单 14. 生成动态 HTML 的通用方式
Array.prototype.fold=function(templateFn) {
var len=this.length;
var str=' ';
for (var i=0 ; i<len ; i++)
str+=templateFn(this[i]);
return str;
}
function templateInstance(element) {
return ... HTML generation code ...
}
document.write(arr.fold(templateInstance));
|
我使用 Array
类型的 prototype 属性定义新函数 fold。现在可以在后面定义的任何数组中使用该函数。
系列函数的应用
考虑以下这种情况:想用一组函数作为回调函数。为实现这一目的,将使用 window.setTimeout
函数,该函数有两个参数。第一个参数是在第二个参数表示的毫秒数之后被调用的函数。清单 15
显示了完成此操作的一种方法。
清单 15. 在回调中调用一组函数
window.setTimeout(function(){alert(‘First!’);alert(‘Second!’);}, 5000);
|
清单 16
显示了完成此操作的更好的方式。
清单 16. 调用系列函数的更好的方式
Function.prototype.sequence=function(g) {
var f=this;
return function() {
f();g();
}
};
function alertFrst() { alert(‘First!’); }
function alertSec() { alert(‘Second!’); }
setTimeout( alertFrst.sequence(alertSec), 5000);
|
在处理事件时,如果想在调用完一个回调之后再调用一个回调,也可以使用 清单 16
中的代码扩展。这可能是一个需要您自行完成的一个练习,现在您的兴趣被点燃了吧。
结束语
在许多领域中都可以应用 JavaScript 中的函数式编程,以优美的方式完成日常活动。这篇文章中的示例只介绍了几种情况。如果您找到了函数式编程的合适场景,并应用这些概念,那么您就会有更多的理解,并且可以增加您的优美程度。
参考资料
学习
获得产品和技术
-
免费下载和学习资源
:使用来自 developerWorks Web 架构专区的文章、教程和下载改进您的工作。
讨论
关于作者
 |
|
 |
Shantanu
Bhattacharya 曾为各类应用程序软件大量设计和创建架构,这些软件中包括零售、系统集成、卫生保健软件;基于 SNMP 和 TCP/IP
堆栈的网络软件;安全软件;印度第一台超级计算机的文件系统;印度导弹项目的实时软件。目前他是一名首席架构师,在西门子位于 Bangalore
的分部从事卫生保健方面的工作。
|
分享到:
相关推荐
函数式编程的一个重要应用是通过使用纯函数和无副作用的原则,来编写可读性更强且更容易维护的代码。文章中提到的示例包括扩展数组排序、动态HTML生成的优美代码、以及系列函数方式的应用。在这些示例中,函数式编程...
在JavaScript中,函数式编程是一种强大的编程范式,它强调使用函数来表示数据处理和计算。函数式编程的核心思想是将程序视为数据的变换,而不是指令的执行序列。这种编程方式可以帮助开发者编写出更加简洁、可读性强...
函数式编程正在以非常好的方式大行其道。 这种编写代码的方式可以强制简化和真正的模块化,从长远来看可以防止头痛。 该领域的一些关键点: 就性能牺牲而言,不变性可能有点过分 matter-js 的可变函数方法还可以吗...
- **简介**:Elixir 是一种运行在Erlang虚拟机上的函数式编程语言。 - **特点**:支持高并发性和容错性。 - **应用场景**:实时系统、分布式系统、Web开发等。 ##### 20. Clojure - **简介**:Clojure 是一种运行在...
《华为编程规范考题解析与深入探讨》 编程规范,如同法律之于社会,是确保代码质量、可读性及团队协作效率的重要基石。...每一位开发者都应该将编程规范视为日常工作的基本准则,从而写出更优美的代码,推动技术进步。
这篇文档“JavaScript中最常用的55个经典技巧”涵盖了该语言的一些核心概念和技术,旨在帮助开发者提升效率,编写更优美的代码。以下是一些重要的JavaScript知识点: 1. **变量声明**:在JavaScript中,可以使用`...
在IT行业中,JavaScript是一种广泛使用的前端编程语言,用于创建交互式的网页应用。"JunAlert.zip"这个文件包提供了一个基于JavaScript实现的特殊警告对话框,称为"自动消失的Alert"。这种功能通常用于向用户显示...
【标签】中的"js"表明该插件是用JavaScript语言编写的,这是网页开发中最常用的一种脚本语言,支持事件驱动、函数式以及基于原型的编程风格。"下拉列表"标签则明确指出了插件主要作用于网页中的选择组件,这些组件...
手册不仅涵盖基础语法和对象,还深入讲解了DOM操作、函数、面向对象编程以及jQuery库的使用,让你能够编写出高效、可维护的代码。 此外,手册还会涉及服务器端技术,如PHP和Python,它们常用于处理动态数据和与...
React式函数式编程 (RFP) 可以帮助您以优美的方式编写复杂的异步场景。 您可以轻松编写自动建议逻辑、乐观操作和其他复杂的异步功能,而不会出现混乱。 这个库可以帮助你以流畅、优雅的方式做到这一点,而无需...
模板文件通常使用Django的模板语言编写,它可以与Bootstrap的CSS和JavaScript组件结合,实现动态数据渲染和交互式界面。 总的来说,"python3 django+mysql+bootstrap增删改查"是一个全面的Web开发教程,涵盖了从...
jQuery 是一款轻量级的JavaScript库,它的目标是使JavaScript编程变得更加简单。它通过提供易于使用的API,简化了DOM操作、事件处理、动画效果和Ajax交互。由于其跨浏览器的兼容性和强大的功能,jQuery在Web开发领域...
了解JavaScript的基本语法、DOM操作、异步编程(如Promise和async/await)以及ES6新特性(如箭头函数、模板字符串等)对于理解和修改这个项目至关重要。 5. 文件结构分析: "E9rayti-main"可能包含了项目的主要源...
第5章 正确、优美、迅速(按重要性排序):从设计XML验证器中学到的经验 5.1 XML验证器的作用 5.2 问题所在 5.3 版本1:简单的实现 5.4 版本2:模拟BNF语法——复杂度O(N) 5.5 版本3:第一个复杂度O(log N)的优化 5.6 ...