引言 - Introduction
-
出于我们自己的目的,我们创造了计算机。我们确信我们是照着我们自己镜像来创造它的... 然而,计算机和我们并不是完全相像。它只是我们非常微小的一部分的折射,这包括:逻辑性,有序性,规则性和清晰性。- Ellen Ullman,Close to the Machine: Technophilia and it's Discontents
这是一本介绍计算机的书籍。虽然现在计算机和螺丝刀一样普通,但它们还是相当复杂。要想让它们按你所想来完成任务不总是一件容易的事。
对于一个常见的、简单的任务,例如电子邮件客服端或计算器,您可以找到相应的应用程序。但对于特殊的或开放式的任务,可能就没有相应的应用程序了。
这就是为什么有编程这个行当(还有一群苦逼的程序猿)。编程是构建程序的过程:写下一组精确的指令,告诉计算机该做什么。因为计算机是愚蠢的,迂腐的野兽,编程基本上是乏味和令人沮丧的。
幸运的是,如果你能够克服这个事实,甚至可以享受严格的思考,最好让愚蠢的机器任你摆布,那么编程就是很有成就感。它可以让你做在几秒钟内完成手工永远做不完的事情。您可以让计算机帮您完成以前无法做到的事情。它还锻炼您的抽象思维。
大多数编程都是用编程语言完成的。编程语言是用于给计算机发送指令的人工构建的语言。有趣的是,我们发现与计算机进行通信的最有效方式是从我们彼此通信的方式中借鉴的。与人类语言一样,计算机语言允许以新的方式组合单词和短语,从而可以表达新的概念。
起初,黑底白字界面,例如20世纪80年代和90年代的BASIC和DOS命令行,是与计算机交互的主要方法。它们在很大程度上被视觉界面所取代,视觉界面更容易学习,但提供的自由度变低。如果你知道在哪里看,计算机语言仍然存在。所有Web浏览器都内置了一种这样的语言JavaScript,因此它几乎可以在所有设备上使用。
本书将试图让您熟悉这种语言,以便用它来做有用和有趣的事情。
关于编程
除了解释JavaScript之外,我还将介绍编程的基本原理。事实证明,编程很难。基本规则简单明了,但基于这些规则构建的程序往往变得十分复杂,并且引入自己的规则和复杂性。你在某种程度上构建自己的迷宫,并且受困其中。
有时阅读这本书会让人非常沮丧。如果你不熟悉编程,那么就会有很多新材料需要消化。然后,大部分材料是互相联系的,需要被合并在一起使用。
掌握知识需要自己努力。当你努力学习这本书时,不要对自己的能力有任何结论。只要你可以坚持下去就好。休息一下,重读一些材料,并确保阅读并理解示例程序和练习。学习是一项艰苦的工作,但是等你学到的以后它就是你的了,并且会使后续的学习变得容易。
“When action grows unprofitable, gather information; when information grows unprofitable, sleep.” - Ursula K. Le Guin,黑暗的左边
(梵总注:当碰到读不懂的地方,就到网上查找更多资料,如果找到的资料不起作用,那么就去睡觉,睡醒后再来。)
一个程序包含很多东西。它是由程序员键入的一段文本,它是使计算机完成它所做的事情的指令,它是计算机内存中的数据,但它控制着同一内存上执行的操作。试图将程序与我们熟悉的对象进行比较往往不尽如人意。程序就好比是机器,它是由很多单独的部件组合在一起,并且相互作用达到要实现的功能。我们必须考虑如何让这些部件互连,从而有助于整体的操作。
计算机是物理机器,充当这些非物质机器的主机。计算机本身只能做愚蠢的事情。他们如此有用的原因是他们可以以极快的速度做这些事情。程序可以巧妙地结合大量这些简单的动作来完成非常复杂的事情。
程序是思想的建构。它是无成本的,它是无重量的,它在我们用手一行行打出来的。
但是,如果不小心,程序的大小和复杂性将会失去控制,甚至会使创建它的人感到困惑。控制程序是编程的主要问题。当一个程序工作时,它应该很完美的。编程艺术是控制复杂性的技能。完美的程序应该是在其复杂性里变得简单。
一些程序员认为,通过仅使用一小部分易于理解的技术来编程可以到达最好地管理这种复杂性。他们制定了严格的规则(美其名曰:“最佳实践”),规定了程序应该具有的形式,并小心地保持在他们安全的小区域内。
这不仅无聊,而且无效。新问题通常需要新的解决方案。编程领域很年轻,并且仍在迅速发展,而且它的变化足以为不同的方法提供空间。虽然在程序设计中你会犯许多可怕的错误,但是你应该继续尝试以便理解它们。好的程序是在实践中发展起来的,而不是从一系列规则中学到的。
语言为何重要
一开始,在计算机诞生之初,就没有编程语言。程序看起来像这样:
00110001 00000000 00000000 00110001 00000001 00000001 00110011 00000001 00000010 01010001 00001011 00000010 00100010 00000010 00001000 01000011 00000001 00000000 01000001 00000001 00000001 00010000 00000010 00000000 01100010 00000000 00000000
这是一个将数字从1到10加在一起并打印出结果的程序:1 + 2 + ... + 10 = 55。它可以运行在一台简单的假想机器上。要对早期的计算机进行编程,必须在正确的位置设置大型开关阵列,或者在纸板条上打孔并将它们送入计算机。你可以想象这个程序是多么乏味和容易出错。即使编写简单的程序也需要很多智慧和纪律。复杂的程度几乎是不可思议的。
当然,手动输入这些神秘的位模式(1和0)确实给程序员一种成为一个强大的巫师的深刻感觉。能搞定这么复杂的矩阵,一定相当有成就感。
前一个程序的每一行都包含一条指令。它可以解释为:
- 将数字0存储在内存位置0中。
- 将数字1存储在内存位置1中。
- 将内存位置1的值存储在内存位置2中。
- 从内存位置2中的值中减去数字11。
- 如果存储器位置2中的值是数字0,则继续执行指令9。
- 将内存位置1的值添加到内存位置0。
- 将数字1添加到内存位置1的值。
- 继续执行指令3。
- 输出内存位置0的值。
虽然这已经比0101更具可读性,但它仍然相当模糊。使用名称而不是数字作为指令和内存位置会有所帮助。
Set “total” to 0. Set “count” to 1. [loop] Set “compare” to “count”. Subtract 11 from “compare”. If “compare” is zero, continue at [end]. Add “count” to “total”. Add 1 to “count”. Continue at [loop]. [end] Output “total”.
你能看到这个程序的工作原理吗?前两行为两个内存位置提供了它们的起始值:total将用于构建计算结果,并将count跟踪我们当前正在查看的数字。使用compare那一行可能是最奇怪的。该程序想要查看是否count等于11来决定是否可以停止运行。因为我们的假设机器相当原始,它只能测试一个数字是否为零并根据它做出决定。因此,它使用标记的内存位置compare来计算值,用count减去11来判断。如果count不等于11,那么接下来的两行将值添加count到结果中,并count在每次循环中增加1。
这是JavaScript中的相同程序:
let total = 0, count = 1; while (count <= 10) { total += count; count += 1; } console.log(total); // → 55
这个版本为我们提供了一些改进。最重要的是,没有必要指定我们希望程序来回跳转的方式。该while构造负责这一点。只要它给出的条件成立,它就会继续执行它下面的块(用大括号括起来)。那个条件是count <= 10,这意味着“ 计数小于或等于10”。我们不再需要创建临时值并将其与零进行比较,这只是一个无趣的细节。编程语言的部分功能在于它们可以为我们处理无趣的细节。
在程序结束时,在while构造完成之后,使用该console.log操作来写出结果。
最后,如果我们碰巧有方便的函数“range”并且“sum”可用,这就是程序的样子,它分别创建一个范围内的数字集合并计算数字集合的总和:
console.log(sum(range(1, 10))); // → 55
这个演变的寓意是,同一个程序可以用长短,不可读和可读的方式表达。该计划的第一个版本是非常模糊的,而这最后一个几乎是英语描述:“ log the sum of the range of numbers from 1 to 10"。(我们将在看到后面的章节中如何定义像操作sum和range。)
一种好的编程语言可以帮助程序员去考虑高级别的计算机操作。它有助于省略细节,提供方便的构建块(例如while和console.log),允许您定义自己的构建块(例如sum和range),并使这些块易于组合。
什么是JavaScript?
JavaScript于1995年推出,作为在Netscape Navigator浏览器中向网页添加程序的一种方式。此语言已被所有其他主要图形Web浏览器采用。它使现代Web应用程序成为可能 - 它让用户与之直接交互,且无需为每个操作执行去重新加载页面。JavaScript也用于更传统的网站,以提供各种形式的交互性。
值得注意的是,JavaScript几乎与名为Java的编程语言无关。相似的名字的灵感来自营销考虑,而不是两者的相关性。当JavaScript被引入时,Java语言正在大量推广并且越来越受欢迎。有人认为尝试搭乘这一成功出了这个好主意,以致我们现在一直沿用这个名字。
在被Netscape之外采用之后,做标准化的Ecma International组织编写了一个标准文档来描述JavaScript语言的工作方式,以便声称支持JavaScript的各种软件实际上都在讨论同一种语言。这被称为ECMAScript标准。在实践中,术语ECMAScript和JavaScript可以互换使用 - 它们是同一语言的两个名称。
有些人会说JavaScript的可怕之处。其中很多都是真的。当我第一次被要求用JavaScript编写内容时,我很快就开始鄙视它了。它几乎可以接受我输入的任何东西,但是以与我的意思完全不同的方式解释它。当然,这与我无法弄清楚我在做什么这一事实有很大关系,但这里有一个真正的问题:JavaScript在它允许的范围内是荒谬的自由。这种设计背后的想法是,它将使初学者更容易使用JavaScript进行编程。实际上,它主要是因为系统不会向你指出问题,因此更难以在你的程序中发现问题。
不过,这种灵活性也有其优点。它为许多技术留下了空间,这些技术在更严格的语言中是不可能的,正如您将看到的(例如在第10章中),它可以用来克服JavaScript的一些缺点。在正确学习语言并使用它一段时间后,我实际上喜欢 JavaScript。
JavaScript已经发展了好几个版本。大约在2000年到2010年之间,ECMAScript版本3成为了广泛支持版本。在此期间,一个雄心勃勃的版本4正在进行工作,该版本计划对该语言进行一些激进的改进和扩展。以这种激进的方式改变广泛使用的语言在组织内很难通过,并且在2008年放弃了版本4的工作,导致了一个远没那么雄心勃勃的版本5,这在2009年出现了一些无可争议的改进然后在2015年第6版出来了,这是一个重大更新,其中包括为版本4计划的一些想法。从那时起,我们每年都有新的,小的更新。
语言不断发展这一事实意味着浏览器必须不断跟上,如果您使用的是较旧的浏览器,则可能无法支持所有功能。语言设计人员通常会很小心,不做任何可能破坏现有程序的更改,因此新浏览器仍然可以运行旧程序。在本书中,我使用的是2017版JavaScript。
Web浏览器不是唯一使用JavaScript的平台。一些数据库(如MongoDB和CouchDB)使用JavaScript作为脚本和查询语言。用于桌面和服务器编程的几个平台,尤其是Node.js项目(第20章的主题),提供了一个在浏览器之外编写JavaScript的环境。
代码,以及如何使用它
代码是组成程序的文本。本书中的大多数章节都包含很多代码。我相信阅读代码和编写代码是学习编程不可或缺的部分。看这些例子是尽量不要走马观花,请仔细阅读并理解它们。起初这可能很慢而且令人困惑,但我保证你会很快掌握它。练习也是如此。在你真正编写有效的解决方案之前,不要认为你理解它们。
我建议您尝试使用实际的JavaScript解释器练习解决方案。这样,你就可以立即得到代码的运行结果,而且,我希望你会经受试验并不断提高。
在运行本书中定义的程序,需要注意一些事项。许多示例都独立存在,应该适用于任何JavaScript环境。但是后面章节中的代码通常是针对特定环境(浏览器或Node.js)编写的,并且只能在那里运行。此外,许多章节定义了更大的程序,并且它们中出现的代码片段彼此依赖或依赖于外部文件。该沙盒提供给定的章节的所有脚本和数据文件,你可以下载他们到本地来运行。
本书概述
本书大致包含三个部分。前12章讨论了JavaScript语言。接下来的七章是关于Web浏览器以及JavaScript用于编程的方式。最后,两章专门介绍Node.js,另一个用于编写JavaScript的环境。
在整本书中,有五个项目章节,它们描述了更大的示例程序,让你体验实际的编程。为了让界面更加生动,我们将通过构建交付机器人,编程语言,平台游戏,像素绘画程序和动态网站来完成工作。
本书的语言部分从四章开始,介绍了JavaScript语言的基本结构。它们引入了控制结构(例如在本简介中看到的“while"),函数(编写自己的构建块)和数据结构。在这之后,您将能够编写基本程序。接着,章节5和6介绍使用的函数和对象来编写更抽象的代码和保持对复杂的控制。
在第一个项目章节之后,本书继续有关于错误处理和错误修复的章节,正则表达式(用于处理文本的重要工具),模块化(针对复杂性的另一种防御)和异步编程(处理事件慢慢来)。在第二个项目章总结了本书的第一部分。
第二部分,第13章到第19章,描述了浏览器JavaScript可以访问的工具。您将学习如何在屏幕上显示的东西(章14和17),用户输入(响应第15章),并在网络中通信(第18章)。本部分还有两个项目章节。
之后,第20章描述了Node.js,第21章使用该工具构建了一个小型网站。
印刷约定
在本书中,用monospaced字体书写的文本将代表程序的元素 - 有时它们是自给自足的片段,有时它们只是指附近程序的一部分。程序(您已经看过几个)编写如下:
function factorial(n){ if(n == 0){ return 1 ; } else { return factorial(n - 1)* n ; } }
有时,为了显示程序产生的输出,预期的输出会在它之后写入,前面有两个斜杠和一个箭头。
console.log(factorial(8)); // → 40320
祝你好运!
-- 梵总(j4fun.com)根据谷歌翻译完成于2018年7于21日 (转发请注明出处)