心智的活动,除了在各种简单概念上显示其威力外,主要表现在如下三个方面:( 1 )把若干简单概念组合为一个复合概念,并由此产生各种复杂的概念。(2)把两个概念放在一起观察,无论其如何简单或复杂,在这样做时并不把它们合而为一,只为得到有关它们的相互关系的概念。(3)把关注的概念与那些在实际中和它们同在的所有其他概念隔离,这称为抽象,所有普适概念都是这样得到的。
——John Locke(约翰·洛克),《人类理解论》(1690)
我们准备学习的是有关 计算过程 的知识。计算过程是与计算机密切相关的一类抽象物,在其演化进程中,会去操作一些称为 数据 的抽象事物。人们创建出一些称为 程序 的规则模式,用以制导计算过程的进行。从作用上看,就像是我们在通过自己写作的魔力去控制计算机里的精灵。
计算过程确实很像一种能控制精灵的巫术,它看不见也摸不着,根本就不是物质构成的。然而它却又非常真实,可以完成某些智力性工作。它可以回答提问,可以通过在银行里支付金钱或者在工厂里操纵机器人等方式影响这个世界。我们用于指挥这种过程的程序就像巫师的咒语,它们是用一些诡秘而深奥的 程序设计语言 ,通过符号表达式的形式细心编排而成,描述了我们希望相应计算过程完成的工作。
在正常工作的计算机里,一个计算过程将精密而准确地执行程序。这样,初学程序设计的人就像巫师的徒弟,必须学习如何理解和预知他们发出的咒语的可观察效果。程序里即使有一点小错误(常被称为 程序错误, bug),也可能带来复杂而且无法预料的后果。
幸运的是,学习程序的危险远远小于学习巫术,因为我们要去控制的精灵以一种很安全的方式被约束着。在真实世界里做程序设计需要极度细心,需要经验和智慧。例如,在计算机辅助设计系统里的一点小毛病,就有可能导致一架飞机或者一座水坝的灾难性损毁,或者一个工业机器人的自我毁灭。
软件工程的大师们有能力组织好自己的程序,他们能合理地确信自己开发出的程序所产生的计算过程能完成预期的工作。他们可以预见自己的系统的行为,知道如何去构造这些程序,使得即使出现意外情况也不会导致灾难性后果。而且,当问题出现时,他们也能 排除 程序中的错误。设计良好的计算系统就像设计良好的汽车或者核反应堆,具有某种模块化的设计,其中各个部分都可以独立地构造、替换、排除错误。
用JavaScript编程
为了描述计算过程,我们需要一种合适的语言。我们为此将要使用的程序设计语言是JavaScript。正如我们日常用自然语言(如英语、瑞典语或汉语等)表述自己的想法,用数学形式的记法描述定量的现象一样,我们将用JavaScript表述过程性的思想。JavaScript是1995年开发的一种程序设计语言,其设计目标是用于写嵌在网页里的脚本,控制万维网(World Wide Web,WWW)浏览器的行为。Brendan Eich设计了这个语言,最初的名字是Macha,后来被更名为LiveScript,最后改为JavaScript。语言名“JavaScript”现在是甲骨文公司(Oracle Corporation)的商标。
虽然JavaScript的初始设计目标是作为写万维网脚本的语言,但实际上它也是一种通用的程序设计语言。JavaScript 解释器 就像一台机器,它能实际完成用JavaScript语言描述的计算过程。第一个JavaScript解释器是Eich在Netscape通信公司为Netscape Navigator开发的。JavaScript的核心特征来自程序设计语言Scheme和Self,其中Scheme是Lisp语言的一种方言,也就是这本书的原版中使用的程序设计语言。JavaScript继承了Scheme最基本的设计原则,例如具有词法作用域的一等函数和动态类型检查等。
虽然JavaScript的最终名称源自Java,而且这两种语言都采用了C语言的块结构,但JavaScript与Java语言的相似只是在表面上。Java和C通常都用编译到低级语言的方式实现,而JavaScript程序自开始就是由万维网浏览器 解释 执行。在Netscape Navigator之后,其他万维网浏览器也提供了该语言的解释器,包括微软的Internet Explorer,它支持的JavaScript版本称为JScript。由于JavaScript被广泛用于控制万维网浏览器,这样就产生了标准化的需求,相关工作最终体现为ECMAScript标准。Guy Lewis Steele Jr.领导了第1版ECMAScript标准的工作,在1997年6月完成(ECMA 1997)。其第6版标准的工作由Allen Wirfs-Brock领导,称为ECMAScript 2015,2015年6月被ECMA全体会议接受(ECMA 2015)。
在实际中,许多JavaScript程序被嵌在万维网网页里,这种情况促使浏览器的开发者实现JavaScript的解释器。随着这种程序变得越来越复杂,执行它们的解释器也变得更加高效,其中通常使用了非常复杂的实现技术,例如即时(Just-In-Time,JIT)编译等。到本书撰写时(2021年),大部分JavaScript程序还是嵌在网页里,由浏览器解释执行。但JavaScript也越来越多地被当作通用程序设计语言使用,例如通过Node.js系统。
ECMAScript 2015拥有一集重要特征,这些特征使它成为绝佳的媒介,能用于研学重要的程序设计结构和数据结构,理解它们与支持它们的语言特征之间的联系。ECMAScript 2015的具有词法作用域的一等函数和通过lambda表达式对它们的语法支持,使我们能直接而且简洁地访问函数抽象;动态类型规则使这个改编本能尽可能接近基于Scheme的原书。除了上面这些因素和一些其他考虑,用JavaScript编程本身也是非常有趣的。