第1章 对象和原型
练习不会造就完美,只有使用最佳的方法来练习才能造就完美。
——Vince Lombardi
对专家来说,把JavaScript的核心概念讲上3章似乎有点多,毕竟这些是语言最基本的组成部分。我的主张是,有的人虽然不能读写,但可以说话。就像有的开发人员对JavaScript的基本功能很熟悉,但对里面那些复杂的东西可能就没那么了解了。
本书的目标是像明灯一样照亮语言中那些晦涩的角落。里面包含的很多概念你可能已经试着学习过了,甚至可以假设你已经理解了。这里可以想象一下:你正降落到你大脑中储存着JavaScript的那一个房间。本书可以被看作是一盏探照灯,用来检查你的JavaScript根基中那些有裂纹的地方。本章和下面的章节是用来弥补你的JavaScript知识漏洞的。不要觉得回顾这些知识没用,这其实是对JavaScript知识结构的重新梳理。
我会先高度概括一下JavaScript的语言目标。但你知道它之前,放平你的肚子,匍匐穿过JavaScript中那些鲜为人知的概念。我会首先详细介绍跟对象和原型相关的重要思想,然后在接下来的章节中介绍函数和闭包,这些都是JavaScript的基础。
1.1 鸟瞰JavaScript
我们所说的JavaScript实际上是ECMAScript语言规范的一个实现。JavaScript若想被看作实现ECMAScript规范的一个有效版本,它必须支持规范中定义的语法和语义。作为ECMAScript的实现,JavaScript必须给程序员提供可使用的多种类型(types)、属性(properties)、值(values)、函数(funtion)和一些保留字(reserved words)。
一旦JavaScript的某个版本已经符合了ECMAScript规范,那么语言设计者就可以自由地对版本进行加强,加入他们认为合适的额外功能和方法。ECMAScript规范中明确说明允许这样的扩展,正如下面读到的:
符合标准的ECMAScript实现,允许提供超出本规范描述的额外类型、值、对象、属性和函数。尤其是本规范中描述的对象,允许提供未在本规范中描述的属性和值。一个合乎ECMAScript规范的实现允许加入没有在规范中描述的程序语法和正则表达式语法。
在ECMAScript中,一些额外的特性可以与核心要素并行存在,但仍然被认为是一种有效的ECMAScript标准的实现,这是ECMAScript标准组织发展的一个标志。ECMAScript对特性的要求比较宽泛,这带来了一些好处但也有弊端。虽然灵活地添加新功能,可以鼓励语言设计者的创新,但也会让开发者处于一个不利的状况:他们会为了支持不同的实现和运行环境而写一些代码(polyfills)1。
ECMAScript的规范会因为各种不同原因(原因太多,不一一列举)不断变化。根本上讲,这些变化是为了使用新的方法来解决老的问题,或者用于支持在巨型计算生态系统中的改进。而不断变化的规范就形成了语言的逐步进化。因此,虽然我要讲的是“核心概念”,它们听起来是不变的,但其实并非如此。本章探讨的概念是那些最基本和重要的,但不要忘记,时刻要准备应对新变化的到来。
脚本设计
正如其名称所示,ECMAScript是脚本语言,使用程序化的方式与主机环境进行交互。无论是浏览器、服务器或单片机,都可以为JavaScript暴露一些可操作的接口。大多数宿主环境仅允许JavaScript去触发那些本来用户就可以操作的功能(虽然用户是手动的)。例如,在浏览器中,用户可以使用鼠标或手指在网页链接上单击,JavaScript则可以用程序的形式完成单击的操作,如下所示:
从传统观念上讲,ECMAScript几乎专门被设计成一种工具,用于在浏览器中编写网络脚本。开发人员用它来提升浏览网页时的用户体验。如今,ECMAScript能用于服务器上,就像它被应用到浏览器中一样,这一切归功于V8或TraceMonkey这样的独立引擎。
ECMAScript标准组织预见到开发人员使用JavaScript的传统方式和它目前成长的领域非常不一样。在最近的规范中它聪明地界定了什么是“网络脚本”,同时列举了两个当下比较流行的应用情境。
Web浏览器为ECMAScript在客户端的运行提供了宿主环境,它封装了一系列对象供ECMAScript使用,包括窗口、菜单、弹窗、对话框、文本区域、锚点、多窗口的页面、历史、cookie和输入/输出对象。此外,宿主环境提供了一种方式,将脚本代码附着在事件上,例如焦点的改变,页面和图像的加载、卸载,错误和中断,选择,表单提交和鼠标操作。含有脚本代码的HTML和被显示的页面是一种组合,脚本代码提供用户接口,而显示页面则提供静态或动态的文字和图片。脚本代码用于响应用户交互,也就不必要有个主程序了。
Web服务器为服务端的计算提供了不同的宿主环境,包括代表请求、客户端和文件的对象,还包括锁定以及共享数据的机制。在浏览器和服务端同时使用脚本语言,使得将计算逻辑分布到客户端和服务端的同时能为基于Web的应用提供定制化的用户接口。
每个支持ECMAScript的Web浏览器和服务器,都需要有满足ECMAScript运行的宿主环境。
注
在作者写作本书时,最新版本的ECMAScript 6(命名为“Harmony”)已经快要发布了,虽然还没有官方发布,但许多提案修改已经被一些运行时引擎和浏览器支持了。本章会对语言的核心进行详尽说明,其中也包括一些在“Harmony”中刚刚引入的新特性。如果某个特性还没有被大范围支持,我会特别提醒读者注意。