JavaScript面向对象编程指南(第2版)

978-7-115-37270-3
作者: 【加拿大】Stoyan Stefanov
译者: 陆禹淳凌杰
编辑: 陈冀康

图书目录:

详情

本书介绍了JavaScript编程的众多泛型之一,面向对象编程,帮助读者了解到JavaScript编写更多不同功能的应用程序的技巧。本书也有专门一章介绍Web浏览器应用环境编程。本书不需要读者有任何JavaScript知识,适合初学者。

图书摘要

JavaScript面向对象编程指南(第2版)
〔加〕Stoyan Stefanov 〔印〕Kumar Chetan Sharma 著

陆禹淳 凌杰 译

人民邮电出版社

北京

图书在版编目(CIP)数据

JavaScript面向对象编程指南/(加)斯托扬(Stefanov,S.),(印)库马尔著;陆禹淳,凌杰译.--2版,—北京:人民邮电出版社,2015.1

ISBN 978-7-115-37270-3

Ⅰ.①J… Ⅱ.①斯…②库…③陆…④凌… Ⅲ.①JAVA语言—程序设计—指南 Ⅳ.①TP312-62

中国版本图书馆CIP数据核字(2014)第251812号

版权声明

Copyright©2013 Packt Publishing.First published in the English language under the title Object-Oriented JavaScript Second Edition

All rights reseved

本书由英国PacktPublishing公司授权人民邮电出版社出版。未经出版者书面许可,对本书的任何部分不得以任何方式或任何手段复制和传播。

版权所有,侵权必究。

◆著 [加]Stoyan Stefanov [印]Kumar Chetan Sharma

译 陆禹淳 凌杰

责任编辑 陈冀康

责任印制 张佳莹 彭志环

◆人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

三河中晟雅豪印务有限公司印刷

◆开本:800×1000 1/16

印张:23.25

字数:459千字  2015年1月第2版

印数:4001-7000册  2015年1月河北第1次印刷

著作权合同登记号 图字:01-2014-4382号

定价:69.00元

读者服务热线:(010)81055410 印装质量热线:(010)81055316

反盗版热线:(010)81055315

内容提要

JavaScript语言是一种具有高度表达能力的、基于原型特性的、非常灵活的面向对象程序设计语言。本书着重于介绍 JavaScript 在面向对象方面的特性,以为您展示如何去构建强健的、可维护的、功能强大的应用程序及程序库。

本书是《JavaScript面向对象编程指南》的第2版,全书包括8章和4个附录。依次介绍了JavaScript的发展历史、基础性话题(变量、数据类型、数组、循环以及条件表达式)、函数、对象、原型、继承的实现、BOM和DOM等。附录部分包括了学习JavaScript编程常用的参考资源。尤其值得一提的是,本书作者是 JavaScript 设计模式方面的专家,他在本书第 8 章中介绍了几种常用的 JavaScript 编程模式,这也成为他的另一本重要著作《JavaScript模式》(JavaScript Patterns)奠定了基础。

本书全面地覆盖了JavaScript语言的OO特性,同时兼顾基础知识,对初学者来说,是难得的JavaScript佳作。读者不需要具备任何的JavaScript基础知识及项目经验,通过学习这本书,将会在面试有关JavaScript程序设计的职位时游刃有余。

译者序

凌杰把这一版译者序的工作交给了我,这让我苦恼了一阵子。我个人是从来不看序的,技术类的国外翻译作品就更不看译者序了。我相信你们也不会看的,那我就乱写了。

前段时间在网络上看了车洪才老先生编写《阿富汗语词典》的故事。36年,200万字,完稿时已斗转星移。我记得我阅读的时候在往西藏南路地铁站走,看着看着便情不自已,然后在马路边大哭。

我觉得翻译书是一件非常寂寞的工作。它需要强大的精神力去自始而终地执行,这种精神力的重要性甚至要高于对专业水平以及英语水平的要求。这本译作的诞生是对我意志的磨练,我相信我今后也不会忘记这近百个日夜,我是如何阅读、翻译、核对,再阅读、翻译、核对,反反复复,直到终结的这一天,恍若隔世。

然而,书的修成不都如此吗?前有明朝的《永乐大典》,近有车洪才老先生的《阿富汗语词典》。我还看过一部电影《编舟记》,讲述的是一部字典历经十余年的修成。跟他们相比,这本小小的书所花费的心血实在是不值一提。

对于读者也是如此的。我从不相信21天可以学会任何一项技术。在这个领域成为一个专家,并没有比其他领域困难或者容易更多。如同这本书所耗费的我的心力一样,计算机技术将在此生折磨你,成就你(或许它已经这么做了)。而这本书,不过是这漫漫长路的一个驿站。我只不过先于你到此,我只不过是个转述者,如此而已。

我不相信这本书有字典一样漫长的生命。十年、甚至只是五年后,计算机技术的日新月异可能会让本书一文不值,非法网站甚至不愿提供本书的盗版(当然,你应该明白,盗版会多么伤害本书的所有工作者)。然而我们对此坦然以待。如同所有序言要说的:这是一本好书。作为本书原版最认真的读者之一,我保证:如果你是这本书的目标读者,这本书绝不会白白浪费你所付出的时间以及金钱。我们知道这本书终有一天会被时代的洪流所抛弃,但是仍然将这本书如此呈现给你,因为推动这时代向前的正是未来的你,我们乐于见证那一刻的到来——十年前的IE6对自己终将被淘汰的命运毫不畏惧,此刻的本书也是一样。

首先感谢原版的两位作者,没有你们当然就绝不会有这本书。感谢凌杰的努力,让我有机会参与这本书的翻译。成书背后需要很多人的工作,感谢这本书所有工作人员的付出。感谢母亲在我翻译期间对我的支持,虽然她并不确切知道我在做什么,但时值我失业,我决定趁此机会做一些想做的事,她对此没有半分怨言。特别感谢上海市黄浦区图书馆七楼阅览室的工作人员,阅览室良好的秩序全是你们的功劳,也感谢你们没有把自带笔记本的我赶出去。

本书编写中一定有很多错漏及翻译不妥之处。我看到了你们对于第一版的一些反馈,包括但不限于豆瓣读书、亚马逊评论等,感谢你们的意见和建议。对于第二版的反馈,我在此留下一个github地址,希望能够与大家交流:http://github.com/scaret/oojs。

祝你阅读愉快。

陆禹淳

2014-03-09

作者简介

Stoyan Stefanov:Facebook 公司工程师、作家、演说家。他经常会在博客(www.phpied.com)上与一些相关会议中就 Web 开发话题发表独到见解。他还运营着其他一些网站,其中包括JSPatterns.com——一个专门探讨JavaScript模式的网站。Stoyan曾在Yahoo!公司任职,担任YSlow 2.0 架构师职务,并且是图像优化工具Smush.it 的作者。

谨以此书献给我的妻子Eva,及我的女儿Zlatina和Nathale。感谢你们的耐心、支持与鼓励。

也将此书献给我的编辑们。你们自愿将时间投入本书草稿的审读中。请接受我由衷的敬意——非常感谢你们无价的投入。

Kumar Chetan Sharma 原本一直致力于成为一个电子工程师,并梦想着打造一个终极音响系统。但由于一次偶然的机会,他得到了一份与HTML相关的兼职,然后自然地学习了CSS和JavaScript,从此便一发不可收拾。要知道在那个年代,JavaScript基本上还只能用来验证表单和制作一些奇特的DHTML效果,且IE6还在世界范围内独占鳌头。但就从那时起,他就已经在开发基于LAMP架构的Web应用了。从白色标签的社交网络应用,到为电信运营商制作的Web控制面板,再到联网的电子充电设备,都有他开发的身影。目前他在Yahoo!公司的搜索部门从事前端工程师的工作。

审阅者简介

Alex R. Young:工程学硕士,拥有超过10 年的Web 与移动行业经验。

他还是DailyJS网站的首席专栏作家,定期以JavaScript为主题撰写文章。他曾在多家知名跨国公司工作,其中包括Thomson Reuters。目前他在写一本Node 方面的书。

前言

本书是《JavaScript面向对象编程指南》的第二版。前一版由Stoyan Stefanov 著(Packet出版社发行),在业界广受好评。然而,自第一版发行至今已过了五个年头。期间,JavaScript由一项主要适用于浏览器客户端的计算机技术,逐渐发展成为一种多功能的程序设计语言,甚至连服务端也能由它来编写。所以在这一版中,我们继续带领大家学习JavaScript的“语言部分”,即其重心依然会放在 JavaScript 语言本身(独立于运行环境部分),着重讨论ECMAScript、JavaScript面向对象编程、模式,原型继承以及设计模式。

本书不会对读者的JavaScript基础知识及项目经验做任何假设。您完全可以从零开始,从本书学习这门语言。同时,对 JavaScript 有一定基础的读者也可以从中学到更多有用的知识。另外,我们在每一章的末尾都设有习题,以便帮助读者了解自己的学习进度。

本书所涵盖的内容

■第1章:面向对象的JavaScript 简单阐述了JavaScript 这门语言的历史、现状及未来。另外,我们还对面向对象程序设计中的基础概念做了一些介绍,并详细说明了该语言调试环境(Firebug)的安装、设置及应用示范。

■第2章:基本数据类型、数组、循环及条件表达式讨论语言中的一些基础性话题,包括变量、数据类型、数组、循环以及条件表达式。

■第3章:函数讨论的是 JavaScript 中函数的使用方法。在这一章中,我们将系统地学习关于函数的一切内容。另外,我们还会了解变量作用域以及内建函数的相关内容。其中有一个叫做“闭包”的概念非常有趣,但也很不容易理解,在该章末尾,我们会重点介绍。

■第4章:对象介绍的是 JavaScript 中的对象类型。在这一章中,我们将学习如何使用对象的属性与方法,以及创建对象的各种方式。另外,我们还会讨论JavaScript中的内建对象,例如Array、Function、Boolean、Number、String等。

■第5章:原型介绍 JavaScript 中有关原型的所有重要概念。包括原型链的工作方式、hasOwnProperty()方法,以及JavaScript中的原型陷阱等。

■第6章:继承讨论如何在JavaScript中实现继承。该章会探讨在JavaScript中创建子类的一种方式,就像那些基于类的面向对象编程语言一样。

■第7章:浏览器环境介绍浏览器相关的内容。在这一章中,我们将会了解到有关BOM(Browser Object Model,浏览器对象模型)和DOM(W3C 的Document Object Model,文档对象模型)的知识,并进一步了解与浏览器事件和AJAX 相关的内容。

■第8章:编程模式与设计模式归纳性地介绍几种专用于 JavaScript 的编程模式,以及若干个与语言无关但适用于JavaScript的设计模式。这些模式大部分来自《设计模式》(GoF)这本书。另外,该章也会对JSON有所讨论。

■附录A:保留字列出了JavaScript中的保留字。

■附录B:内建函数是一份JavaScript中内建函数的参考指南,并附有简单的使用范例。

■附录C:内建对象是一份JavaScript中内建对象类型的参考指南,它提供了详细的对象方法、属性介绍和使用示例。

■附录D:正则表达式是一份正则表达式模式的参考指南。

您可以从下面这个链接获取参考答案的电子版:http://www.packtpub.com/sites/default/files/downloads/3127OT_Answers_to_Exercise_Questions.pdf。

前期准备

在阅读本书之前,您需要安装一个现代浏览器——推荐Google Chrome或者Firefox,并可自由选择是否安装Node.js。虽然最新版本的Firefox自带了Web开发者工具,但我们还是非常推荐您使用Firebug插件。当然,您可以自行选择用于编写JavaScript代码的文本编辑器。

适用对象

本书适用于任何希望学习JavaScript的编程初学者,包括那些懂一点JavaScript,却对其面向对象特性不甚了解的读者。

一些约定

在这本书中,读者会发现几种不同样式的文本,它们各自代表了不同类型的信息。下面,我们将通过一些文本实例来解释一下这些样式各自所代表的含义。

对于一段文本中的代码,我们将以如下形式来表现:“你可以通过检查事件对象的cancellable属性来确认”。

而对于代码块文本,我们将采用如下格式:

var a;

var thisIsAVariable;

var _and_this_too;

var mix12three;

当需要提醒你注意代码的输出时,我们会将相关行或项目的字体加粗,例如:

> var case_matters = 'lower';

> var CASE_MATTERS = 'upper';

> case_matters;

"lower"

> CASE_MATTERS;

"upper"

命令行输入及输出会仿照如下格式呈现:

aliasjsc='/System/Library/Frameworks/JavaScriptCore.framework/Versions/Cu rrent/Resources/jsc'

另外,加粗字体还经常用于强调新的术语或重要词汇。例如,我们屏幕上的菜单以及对话框中会看到的单词,通常会这样表述:“在单击Cancel按钮后,preventDefault()方法就会被调用”。

读者反馈

我们始终欢迎任何来自读者的反馈信息。请务必让我们了解您对于这本书的看法——您喜欢本书的哪部分,或者不喜欢本书的哪部分。这些反馈对于我们的选题开发来说都是至关重要的。

对于一般的反馈,您只需简单地给 feedback@packtpub.com 发一份电子邮件,并在邮件的标题中注明这本书的书名即可。

如果您对某一话题有专长,并且有兴趣撰写一本这方面的书(或为某本书作出贡献),请参考我们的作者指南:http://www.packtpub.com/authors。

客户支持

很荣幸您成为这本 Packt 图书的主人,我们将会尽一切努力来帮助您获取最好的图书资讯。

勘误表

尽管我们已经尽了最大努力来确保书中内容的正确性,但错误始终可能存在。如果您在我们的书中发现了错误——无论是关于文字的还是代码的——只要您能告诉我们,我们都将不胜感激。这样也可以大大减少其他读者在阅读方面所遇到的困难。当您发现错误时,只需要访问http://www.packtpub.com/submit-errata,选择相应的书名,然后单击“errata submission form”链接并输入相关错误的详细信息即可。一旦您提供的信息获得了确认,相关的内容就会出现在这本书的勘误表中。我们出版社所有现存的勘误表都可以在http://www.packtpub.com/support中获取。

版权

在互联网上,版权对于所有媒介一直是一个很大的问题。在Packet,我们向来对于版权许可非常重视。如果您在网络上发现我们出版过的作品,无论它是出于什么形式,都请马上将网址或网站名称告知我们,以便于我们采取补救措施。

请将您怀疑有侵权行为的文档链接发送到:copyright@packetpub.com。您付出的帮助是对作者权利的保护,我们也由此才能继续为您带来有价值的内容。

疑问

如果您对本书有任何疑问,也可以通过 questions@packtpub.com 跟我们联系,我们将竭尽所能地替您解决。

第1章 面向对象的JavaScript

自 Web 诞生以来,人们对于动态与响应式页面的需求便与日俱增。虽然静态的HTML文本页面在可读性方面或许会更好一些,特别是在有了CSS的辅助之后,页面排版显得更加美观了,但从另一方面来说,如果我们能让人们像在桌面上那样使用浏览器中的应用程序,事情或许会变得更有趣一些。如今,我们已能在浏览器中直接使用电子邮件、日历、电子银行、购物、绘画、游戏及文本编辑。这都要感谢一种Web编程语言——JavaScript,是它让这些Web应用成为了可能。然而,JavaScript最初也只不过是我们偶尔嵌入在HTML中的一小行代码,但如今它已经日趋成熟,并且被广泛使用。开发者们利用该编程语言的面向对象特性,实现了代码重用,并构建起了可伸缩的代码架构。

如果我们回顾一下Web开发领域这些年来的流行词汇——DHTML、Ajax、Web 2.0、HTML5,就会发现这些词背后的内涵始终没有变,依然是:HTML、CSS、JavaScript。其中HTML服务于内容,CSS服务于表现,而JavaScript则服务于行为。换句话说,JavaScript是让一切东西协同运作的粘合剂,有了它,我们才能在构建出丰富多彩的Web应用程序。

但事情远不止如此,JavaScript的应用领域并不仅仅局限于Web平台。

在 JavaScript 程序所能运行的多种宿主环境中,Web 浏览器无疑是用得最普遍的那一种,但JavaScript也可以运行于其他环境。JavaScript可以应用于各式各样的小工具、应用扩展、以及其他软件,本书在后续章节中会一一提及。总而言之,将时间投资于学习JavaScript 是一个明智的选择,因为一旦您掌握了 JavaScript,就可以编写出各种适用于多种平台的不同应用,包括手机应用和服务器端程序。毕竟,如今我们要说 JavaScript 无所不在,那确实是一点都不夸张。

本书将从零开始,我们不会对读者的编程背景做任何假设,只需要您了解一点HTML常识即可。而且除了有一个章节用于探讨Web浏览器环境以外,本书其他部分都在纯粹地关注JavaScript语言本身。因此,您可以将在本书中学到的知识应用于所有的JavaScript环境。

下面,我们将从以下两点开始:

对JavaScript背后故事的简单介绍;

面向对象。

1.1 回顾历史

起初,Web页面不过是一些以静态HTML文档形式发布的科学出版物,这些文档之间只依靠一些简单的超链接(hyperlinks)绑定在一起。这可能有些难以置信,但最早的Web页面的确是不支持任何图片的,但这种情况不久便得到了改善。随后Web就越来越广受欢迎,规模也在不断增大,很快随着Web业务的快速普及和增长,网站管理者越来越希望自己所创建的Web页面能处理更多的事情。例如,他们希望网站能具有更丰富的用户交互能力,主要是能完成一些简单任务(如验证表单之类),以此节省与服务器端的信息交互。当时他们可以有两种选择:Java applets 和LiveScript。其中,LiveScript是1995年由Netscape公司的 Brendan Eich 所开发的程序设计语言。Netscape 2.0 发布之后,它被正式更名为JavaScript。

众所周知,Applets后来没落了,JavaScript则更加繁荣。这种通过在HTML中嵌入简短代码段来调整Web页面中其他静态元素的方式在网站管理者间大受好评。但没过多久,浏览器的竞争厂商Microsoft 公司就发布了支持JScript的Internet Explorer(IE)3.0。JScript简直就是JavaScript的翻版,并且还在其继承之上引入了一些IE独有的特性。最终,为了使语言的实现更趋向于标准化,于是 ECMAScript 应运而生了。ECMA(欧洲计算机制造商协会)创建了ECMA-262标准,该标准脱离了浏览器和那些Web独有的特性,集中描述了JavaScript作为编程语言的核心部分。

大致上,JavaScript这个术语通常涵盖了以下3个部分。

ECMAScript——语言的核心部分(即变量,函数,循环等等):这个部分独立于浏览器之外,并可以在其他环境中使用。

文档对象模型(DOM):它实际上是提供了一种与 HTML、XML 文档交互的方式。最初,JavaScript 只能提供对页面上一部分元素的有限访问能力,主要集中在表单,超链接和图片这些元素上。后来权限逐渐被扩大,如今几乎所有元素都已经可以访问了。为此,万维网联盟(W3C)还专门创建了DOM标准。该标准是一种独立的(即它并不依赖于JavaScript)操作结构化文档的方式。

浏览器对象模型(BOM):这实际上是一个与浏览器环境有关的对象集合。原本没有任何标准可言,直到HTML5诞生之后,人们才定义了一些浏览器之间通用的对象标准。

虽然本书专门有一个章节用于阐述浏览器、DOM及BOM,但大部分内容还都在讲述JavaScript 语言的核心部分,您在这里所学到的 JavaScript 知识基本都可应用于任何JavaScript执行环境。

1.2 浏览器的战争与复兴

无论结果是好是坏,JavaScript都在随后爆发的第一次浏览器大战(大约是在1996年到 2001 年间)中得到了迅速的普及。那时正值互联网发展处于第一波热潮,其中主要由Netscape和Microsoft这两大浏览器厂商在争夺市场份额。在此过程中,他们不断地把各种浮华的特性添加到各自的浏览器与JavaScript、DOM及BOM中,从而导致了许多不一致性。与此同时,由于浏览器厂商都在忙于继续增加新的浏览器特性,以至于根本没能及时更新相应的工具,这造成了开发工具的严重滞后。这种情况给使用 JavaScript 的开发人员带来巨大的痛苦。我们将某个浏览器里编写与测试过的脚本在另一个浏览器里测试,却发现脚本不能正常工作,而且还没有合适的错误信息,只得到如“操作终止”之类天书般的错误先知。

实现上的不一致,文档的缺乏,甚至连能将 JavaScript 关键字高亮显示的编辑器都没有。这一切都令开发者们再也没法忍受了。

在另一方面,开发者自己也在他们的Web页面中使用了太多的新特性,总迫不及待地想引入浏览器提供的每一项新功能,以“加强”自己的页面。例如状态栏中的动画、闪烁的颜色、闪烁的文本、会摇晃的浏览器窗口、屏幕上的雪花效果、能跟踪对象的鼠标光标等,这不但牺牲了实用性,而且也伤害了用户体验。这些滥用现象如今大多都消失了,但这在当时极大地损坏了JavaScript在业界的名声。许多“专业的”程序员将JavaScript贬低为设计师的玩具,并批评它不适合用来开发专业应用。JavaScript 语言在一些 Web 项目中遭到了强烈抵制。某些项目甚至完全拒绝对浏览器端进行任何的程序设计,转而只信任他们自己可以掌控的服务器端。确实,在当时那种情况下,也没有什么理由值得我们花费双倍的时间来为这些不同的浏览器设计项目,然后再花更多的时间去调试它们。

这种情况一直持续到第一次浏览器大战结束。但在随后的几年中,Web开发领域在一系列历史进程的推动下,终于发生了一些非常积极的变化。

Microsoft 公司依靠新发布的 IE6 赢得了战争。在那时,IE6 虽然的确是最棒的浏览器,但其后数年,他们却停止了对IE的开发,这给了其他浏览器充分的时间,使它们能够在功能上逐步完成对IE的追赶和超越。

Web 标准化运动渐渐被开发人员和浏览器厂商所接受。这是很自然的,毕竟对于开发人员来说,谁也不想因为不同的浏览器而花费双倍(甚至更多)的开发时间,这促使各方都越来越倾向于遵守统一的开发标准。

开发人员和技术本身也日趋成熟了,越来越多的人开始将注意力转移到其他方面,例如可用性、渐进增强技术及可访问性。开发辅助工具(例如Firebug)也让开发变得更高效,减轻了开发者的负担。

在这种健康环境的影响下,开发人员开始谋求一种更好的新型开发模式,以取代这些现有的开发方式。随着Gmail和Google Maps这一类富客户端应用的相继出现,很显然,如今的JavaScript 已经成为一种成熟的、某些方面独一无二的、拥有强大原型体系的面向对象语言。关于这点,最好的例子莫过于是对XMLHttpRequest对象的重新发现和推广,该对象起初不过是一个IE-only特性,但如今已经得到绝大多数浏览器的支持。通过XMLHttpRequest对象,JavaScript 就能以 HTTP 请求的形式从服务器上获取所需的新鲜内容,从而实现了页面的局部更新。这样一来,我们就不必每次都刷新整个页面。随着XMLHttpRequest对象的广泛应用,一种类桌面式的Web应用模式诞生了,我们称之为AJAX应用。

1.3 分析现状

有意思的是,JavaScript 必须运行于某种宿主环境中。Web 浏览器仅仅是其中一种, JavaScript 也完全可以运行在服务器端、桌面以及移动设备中。如今,我们已经可以用JavaScript来实现以下功能。

创建拥有强大而丰富功能的 Web 应用程序(这种应用程序往往运行在 Web 浏览器中)。另外还有基于HTML5的许多特性,例如应用缓存、本地存储、本地数据库。无论是线上应用还是离线应用,Web应用都可以做得非常强大。

使用.NET 和 Node.js 编写服务器端脚本,或者使用 Rhino(这是一种用 Java 实现的JavaScript引擎)这样的框架来进行编程。

为移动设备编写各种应用程序。借助于 PhoneGap 及 Titanium 这样的工具,我们完全可以使用纯JavaScript来编写iPhone、Android或其他平台上应用程序。另外值得一提的是,移动平台 Firefox OS 的原生编程语言就是 JavaScript、HTML 和CSS。

使用 ActionScript 创建富媒体应用(如 Flash、Flex)。ActionScript 也是一种基于ECMAScript标准的脚本语言。

编写各种基于命令行的、用于桌面自动化管理的脚本任务。其自带的宿主环境如Windows Scripting Host 及Mac 下的WebKit JavaScript Core。

为一些桌面应用程序编写扩展或插件,例如Dreamweaver、Photoshop 及大多数浏览器。

使用Mozilla XUIRunner及Adobe Air创建跨操作系统的桌面应用程序。

使用Yahoo! Widgets及Mac Dashboard Widgets等工具包来创建桌面小工具。其中, Yahoo! Widgets还可以在智能电视上运行。

当然,这里列出的远远不是该语言的全部应用。JavaScript应用的确发端于Web页面,但如今几乎可以说是无所不在了。另外,浏览器厂商如今都将运行速度视为产品的竞争优势之一,因此都致力于创建更快的 JavaScript 引擎。这对于用户与开发者来说无疑是个好消息,并且这将打开一扇大门——在新的领域,例如在图像、音频及视频处理、游戏开发等方面,JavaScript也必将一展拳脚。

1.4 展望未来

对于未来的情况,我们这里只能做一些猜测。但几乎可以肯定地说,JavaScript语言必将会有它的一席之地。毕竟,在过去相当长的一段时间里,JavaScript在被严重低估、始终未得到充分利用(或者被错误地滥用了)的情况下,依然几乎每天都能有很多新的、有趣的JavaScript应用被开发出来。一切都是从那行简单的、内嵌于HTML标签中(例如onclick事件)的代码开始的。如今的开发人员所面对的商业开发往往要复杂得多,这需要良好的设计和规划,以及合适的应用扩展和程序库。JavaScript必将在其中得到真正的用武之地,开发人员无疑会更加重视它独有的面向对象特性,以获取越来越多的便利。

曾经被列为职位要求中的“加分项”的 JavaScript,如今已经成为了招聘 Web 开发人员的决定性因素。例如,我们在面试时常会被问到这样的问题:“JavaScript 是一种面向对象语言吗?如果是,JavaScript中的继承关系是如何实现的呢?”在读过这本书之后,您就会对这类面试有充分的准备,甚至还能凭借一些连面试官自己都不知道的知识来打动他们。

1.5 ECMAScript 5

几乎所有的现代浏览器与其他相关环境都实现了ECMAScript的第3版,对此我们可以安心使用。第4版则直接被跳过了。而ECMAScript的第5版(以下简称为ES5)则到2009年12月才被正式采纳。

ES5 中除了引入了一些新的对象与属性外,它还提供了“严格模式(strict mode)”。所谓严格模式其实就是在ES5发布之前,市面上各版互不兼容语言的子集。严格模式是可选的,也就是说,选择以严格模式执行的代码段(以函数为单位,或者整个程序)都必须要在其头部作如下声明:

"use strict";

这其实是一个 JavaScript 字符串。虽然我们并没有将其赋值给某个变量,执行后也不会有什么效果,但它符合JavaScript语法。因此不支持ES5严格模式的老式浏览器会直接忽略它,然后以普通的 JavaScript 对待其后的代码。也就是说,这种严格模式是向后兼容的,使用严格模式不会导致老式浏览器无法执行代码。

或许在将来的版本中,严格模式由可能会成为 ES 的默认模式,甚至是唯一模式。但现在它还只是一个可选项。

出于向后兼容的考虑,本书所有的示例都将遵守ES3规则,但同时本书中所有的代码也都能在ES5严格模式下正常执行,不会有任何警告。另外,本书中专门为ES5所写的部分会被清楚地标记出来。而关于ES5的新特性,我们在附录C,内建对象中会有详细收录。

1.6 面向对象的程序设计

在深入学习 JavaScript 之前,我们首先要了解一下“面向对象”的具体含义,以及这种程序设计风格的主要特征。下面我们列出了一系列在面向对象程序设计(OOP)中最常用到的概念:

对象、方法、属性;

类;

封装;

聚合;

重用与继承;

多态。

现在,我们就来详细了解每个概念。当然,如果您在面向对象程序设计方面是一个新手,或者不能确定自己是否真的理解了这些概念,那也不必太过担心。以后我们还会通过一些代码来为您具体分析它们。尽管这些概念说起来好像很复杂、很高级,但一旦我们进入真正的实践,事情往往就会简单得多。

1.6.1 对象

既然这种程序设计风格叫做面向对象,那么其重点就应该在对象上。而所谓对象,实质上就是指“事物”(包括人和物)在程序设计语言中的表现形式。这里的“事物”可以是任何东西(如某个客观存在的对象,或者某些较为抽象的概念)。例如,对于猫这种常见对象来说,我们可以看到它们具有某些明确的特征(如颜色、名字、体型等),能执行某些动作(如喵喵叫、睡觉、躲起来、逃跑等)。在OOP语义中,这些对象特征都叫做属性,而那些动作则被称为方法。

此外,我们还有一个口语方面的类比[1]

对象往往是用名词来表示的(如book、person)。

方法一般都是些动词(如read、run)。

属性值则往往是一些形容词。

我们可以试一下。例如,在“The black cat sleeps on my head”这个句子中,“the cat”(名词)就是一个对象,“black”(形容词)则是一个颜色属性值,而“sleep”(动词)则代表一个动作,也就是OOP语义中的方法。甚至,为了进一步证明这种类比的合理性,我们也可以将句子中的“on my head”看做动作“sleep”的一个限定条件,因此,它也可以被当做传递给sleep方法的一个参数。

1.6.2 类

在现实生活中,相似对象之间往往都有一些共同的组成特征。例如蜂鸟和老鹰都具有鸟类的特征,因此它们可以被统称为鸟类。在OOP中,类实际上就是对象的设计蓝图或制作配方。“对象”这个词,我们有时候也叫做“实例”,所以我们可以说老鹰是鸟类的一个实例[2]。我们可以基于同一个类创建出许多不同的对象。因为类更多的是一种模板,而对象则是在这些模板的基础上被创建出来的实体。

但我们要明白,JavaScript与C++或Java这种传统的面向对象语言不同,它实际上压根儿没有类。该语言的一切都是基于对象的,其依靠的是一套原型(prototype)系统。而原型本身实际上也是一种对象,我们后面也会再来详细讨论这个问题。在传统的面向对象语言中,我们一般会这样描述自己的做法:“我基于Person类创建了一个叫做Bob的新对象。”而在这种基于原型的面向对象语言中,我们则要这样描述:“我将现有的Person对象扩展成了一个叫做Bob的新对象。”

1.6.3 封装

封装是另一个与OOP相关的概念,其主要用于阐述对象中所包含的内容。封装概念通常由两部分组成。

相关的数据(用于存储属性)。

基于这些数据所能做的事(所能调用的方法)。

除此之外,这个术语中还有另一层信息隐藏的概念,这完全是另一方面的问题。因此,我们在理解这个概念时,必须要留意它在OOP中的具体语境。

以一个MP3播放器为例。如果我们假设它是一个对象,那么作为该对象的用户,我们无疑需要一些类似于像按钮、显示屏这样的工作接口。这些接口会帮助我们使用该对象(如播放歌曲之类)。至于它们内部是如何工作的,我们并不清楚,而且大多数情况下也不会在乎这些。换句话说,这些接口的实现对我们来说是隐藏的。同样的,在OOP中也是如此。当我们在代码中调用一个对象的方法时,无论该对象是来自我们自己的实现还是某个第三方库,我们都不需要知道该方法是如何工作的。在编译型语言中,我们甚至都无法查看这些对象的工作代码。由于 JavaScript 是一种解释型语言,源代码是可以查看的。但至少在封装概念上它们是一致的,即我们只需要知道所操作对象的接口,而不必去关心它的具体实现。

关于信息隐藏,还有另一方面内容,即方法与属性的可见性。在某些语言中,我们能通过 public、private、protected 这些关键字来限定方法和属性的可见性。这种限定分类定义了对象用户所能访问的层次。例如,private 方法只有其所在对象内部的代码才有权访问,而public方法则是任何人都能访问的。在JavaScript中,尽管所有的方法和属性都是public的,但是我们将会看到,该语言还是提供了一些隐藏数据的方法,以保护程序的隐密性。

1.6.4 聚合

所谓聚合,有时候也叫做组合,实际上是指我们将几个现有对象合并成一个新对象的过程。总之,这个概念所强调的就是这种将多个对象合而为一的能力。通过聚合这种强有力的方法,我们可以将一个问题分解成多个更小的问题。这样一来,问题就会显得更易于管理(便于我们各个击破)。当一个问题域的复杂程度令我们难以接受时,我们就可以考虑将它分解成若干子问题区,并且必要的话,这些问题区还可以再继续分解成更小的分区。这样做有利于我们从几个不同的抽象层次来考虑这个问题。

例如,个人电脑是一个非常复杂的对象,我们不可能知道它启动时所发生的全部事情。但如果我们将这个问题的抽象级别降低到一定的程度,只关注它几个组件对象的初始化工作,例如显示器对象、鼠标对象、键盘对象等,我们就很容易深入了解这些子对象情况,然后再将这些部分的结果合并起来,之前那个复杂问题就迎刃而解了。

我们还可以找到其他类似情况,例如Book是由一个或多个author对象、publisher对象、若干chapter对象以及一组table对象等组合(聚合)而成的对象。

1.6.5 继承

通过继承这种方式,我们可以非常优雅地实现对现有代码的重用。例如,我们有一个叫做Person的一般性对象,其中包含一些姓名、出生日期之类的属性,以及一些功能性函数,如步行、谈话、睡觉、吃饭等。然后,当我们发现自己需要一个Programmer对象时,当然,这时候你可以再将Person对象中所有的方法与属性重新实现一遍,但除此之外还有一种更聪明的做法,即我们可以让Programmer继承自Person,这样就省去了我们不少工作。因为Programmer对象只需要实现属于它自己的那部分特殊功能(例如“编写代码”),而其余部分只需重用Person的实现即可。

在传统的OOP环境中,继承通常指的是类与类之间的关系,但由于JavaScript中不存在类,因此它的继承只能发生在对象之间。

当一个对象继承自另一个对象时,通常会往其中加入新的方法,以扩展被继承的老对象。我们通常将这一过程称之为“B继承自A”或者“B扩展自A”。另外对于新对象来说,它也可以根据自己的需要,从继承的那组方法中选择几个来重新定义。这样做并不会改变对象的接口,因为其方法名是相同的,只不过当我们调用新对象时,该方法的行为与之前不同了。我们将这种重定义继承方法的过程叫做覆写。

1.6.6 多态

在之前的例子中,我们的Programmer对象继承了上一级对象Person的所有方法。这意味着这两个对象都实现了“talk”等方法。现在,我们的代码中有一个叫做Bob的变量,即便是在我们不知道它是一个 Person 对象还是一个 Programmer 对象情况下,也依然可以直接调用该对象的“talk”方法,而不必担心这会影响代码的正常工作。类似这种不同对象通过相同的方法调用来实现各自行为的能力,我们就称之为多态。

1.7 OOP小结

下面,让我们再来回顾一下这些概念(见表1-1)。

1.8 训练环境设置

在这本书中,凡涉及代码的我们都强调“自己动手”,因为在我们的理念中,学好一门编程语言最好的途径就是不停地编写代码。因此,这里将不提供任何可供您直接复制/粘贴的代码下载。恰恰相反,我们必须得让您亲自来输入代码,并观察它们是如何工作的,思考需要做哪些调整,这样周而复始地摆弄它们。因而,当您想尝试这些代码示例时,我们建议您使用JavaScript控制台这一类的工具。下面就让我们来看看这些工具是如何使用的。

对于开发人员来说,机器上应该大多都早已安装了一些Web浏览器了,例如Firefox、Safari、Chrome 或Internet Explorer。而所有现代浏览器中都应该自带了JavaScript 控制台组件,该组件是我们在阅读本书过程中始终会用到的东西,是帮助您进行语言学习和实验的环境。更具体地说,尽管本书用的是WebKit控制台(Safari和Chrome都支持该控制台),但书中的这些示例在任何控制台上都是能正常工作的。

1.8.1 WebKit所附带的Web审查工具

图1-1展示了如何在控制台中通过输入代码的方式将google.com主页上的logo换成我们自己指定的图片。如您所见,我们可以在任何页面上测试这段JavaScript代码。

在Chrome和Safari中,您可以通过右键单击相关页面,并选择“审查元素”来打开控制台。然后Web审查工具就会出现在下面的弹出窗口中,我们选择其标签栏上的“控制台”标签,就来到了真正的控制台界面中。

然后,我们直接在控制台中输入代码,按下回车键,代码就会被执行。其返回值也会在控制台中被打印出来。代码会在当前页面的上下文环境中运行,所以,如果您在其中输入location.href,控制台就会返回当前页面的 URL。除此之外,该控制台还具有一套自动完成功能,其工作方式与我们平时所用的操作系统命令行类似。举个例子,如果我们在其中输入docu,然后按Tab键,docu就会被自动补全为document。这时如果再继续输入一个“.”(点操作符),我们就可以通过重复按Tab键的方式来遍历document对象中所有可调用的方法和属性。

另外通过上下箭头键,我们还可以随时从相关列表中找回已经执行过的命令,并在控制台中重新执行它们。

通常情况下,控制台只提供单行输入,但我们可以用分号做分割符来执行多个JavaScript语句。而如果您需要更多行代码的话,也可以通过组合键shift+Enter来实现换行,在这种情况下代码不会被立即执行。

1.8.2 Mac上的JavaScriptCore

在Mac上,我们事实上不用浏览器也可以通过终端来执行JavaScript。

如果您之前没有使用过终端,可以通过Spotlight找到它。打开终端之后,在其中输入:

alias jsc='/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Resources/jsc'

该命令为JSC(即JavaScriptCore)设置了一个别名。JSC其实是WebKit引擎的一部分。Mac系统自带有该引擎。

我们也可以直接将这个alias命令放入~/.profile文件,这样每次打开终端时,都可以通过jsc这个别名来启动JavaScriptCore了。

现在,终端在任何目录下都可以通过直接输入 jsc 来打开其交互环境了。然后您可以在其中输入相关的 JavaScript 表达式。按下 Enter 键之后,表达式的结果就会被显示出来,如图1-2所示。

1.8.3 更多控制台

如今,几乎所有现代浏览器都有自带的控制台。除了之前提到的Chrome及Safari的控制台之外,FireFox浏览器的所有版本也都能安装Firebug组件,该组件中也有一个控制台。另外,新版的Firefox中也有一个自带的控制台,您可以通过菜单栏“工具/Web开发者/Web控制台”来打开它,如图1-3所示。

而Internet Explorer从第8版开始,只要按下F12键就可以打开开发者工具组件。打开后,按Script标签栏就可进入控制台。

另外,通过 Node.js 的交互环境来学习 JavaScript 也是一个不错的选择。您可以从http://nodejs.org中获取并安装Node.js,然后在终端中尝试其控制台,如图1-4所示。

如您所见,我们既可以用Node.js的控制台测试一些小型示例,同时也可以写一些较长的shell脚本(如截图中的test.js),然后以scriptname.js的形式在Node.js的终端中执行。

1.9 本章小结

在这一章中,我们首先介绍了 JavaScript 语言的发展历程和现状。然后,对面向对象程序设计的概念进行了一些基本论述。接着,我们向您详细阐述了为什么 JavaScript 不是传统的基于类的面向对象语言,而是一套独特的原型系统。现在,您已经为下一步深入学习JavaScript语言、掌握其面向对象特性打下了一定的基础,但让我们一步步来。

下一章将会介绍JavaScript的数据类型(JavaScript的数据类型非常少),以及条件、循环语句和数组。如果您确信自己已经掌握了这些知识,并且对该章结尾处的那几个小练习完全没有疑问的话,那么就请自行跳过这一章吧。

注 释

[1].这里应该特指英文环境,在中文这种形而上的语言环境中,这种类比或许并不是太合适。——译者注

[2].至少在中文环境中,老鹰更像是鸟类的一个子类。希望读者在理解对象与类的关系时,不要过分依赖这种类比。——译者注

相关图书

深入浅出Spring Boot 3.x
深入浅出Spring Boot 3.x
JavaScript核心原理:规范、逻辑与设计
JavaScript核心原理:规范、逻辑与设计
JavaScript入门经典(第7版)
JavaScript入门经典(第7版)
JavaScript函数式编程指南
JavaScript函数式编程指南
PHP、MySQL和JavaScript入门经典(第6版)
PHP、MySQL和JavaScript入门经典(第6版)
JavaScript学习指南(第3版)
JavaScript学习指南(第3版)

相关文章

相关课程