七种武器:编程语言集锦(套装共7册)(txt+pdf+epub+mobi电子书下载)


发布时间:2020-06-22 12:06:01

点击下载

作者:[美] Joshua D. Suereth 苏瑞茨 著

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

七种武器:编程语言集锦(套装共7册)

七种武器:编程语言集锦(套装共7册)试读:

前言

JavaScript非常重要。这并不总是如此,但现在确实如此。

Web应用程序将为用户提供丰富的用户界面体验,没有JavaScript,我们也就只能显示几张小图片。Web开发人员比以往任何时候都更需要熟练掌握能够为Web应用程序带来生命的语言。

像橙汁和早餐一样,JavaScript不再只用于浏览器了。该语言推倒了浏览器的界限,可用在Rhino和V8等引擎的服务器上,也可以用于像node.js这样的框架。

虽然本书主要是介绍用于Web应用程序的JavaScript,但本书第二部分提出的JavaScript基础适用范围也很广泛。

随着使用JavaScript的开发人员在逐渐增多,熟练掌握JavaScript基础比以往任何时候都更加重要,这样他们就可以成为真正的语言忍者。目标读者

这本书不能作为你的第一本JavaScript图书。如果你是JavaScript完全新手,或者只是通过搜索网络获得代码片段了解了一些语句,那么本书还不适合你阅读。

本书面向至少掌握JavaScript基础的Web开发人员。你应该理解JavaScript语句的基本结构以及创建简单页面脚本的工作原理。你不需要是该语言的高级用户——这是本书的目标,但你不应是一位新手。

你还应该有HTML和CSS方面的工作经验。再次强调,不需要了解特别高级的知识,但你应该知道拼凑Web网页的基础知识。

如果你想获得一些好的必备资料,寻找一本关于JavaScript和Web开发方面的流行图书,然后解决这个问题。我们推荐的JavaScript图书:David Flanagan的《JavaScript权威指南》、Douglas Crockford的《JavaScript语言精粹》以及Michael Morrison的Head First JavaScript。路线图

本书旨在通过四个部分让你从学徒升级为忍者。

第一部分介绍了我们往下要学习的主题和所需要的一些工具。

第二部分主要关注JavaScript基础:该语言中你习以为常但不太清楚其工作原理的部分。这可能是本书中最重要的部分,即使你只阅读了该部分,也会对JavaScript语言有更深入的理解。

在第三部分,我们利用在第二部分中学到的基础知识解决浏览器留给我们的棘手问题。

第四部分总结本书内容,主要讨论从创建jQuery等高级JavaScript库中学到的东西。

让我们看一下每一章的简要内容。

第1章介绍我们作为高级Web应用程序作者所面临的挑战。提出浏览器扩散引起的一些问题,并针对我们在开发包括测试和性能分析在内的应用程序时应该遵循的最佳实践给出建议。

第2章讨论测试,了解测试和测试工具的当前状态。还介绍一个小而强大的测试概念——断言,我们将在本书的其余部分大量使用它,以确保代码完成我们希望它完成的事情(有时是为了证明它不应该这样做!)。

有了这些工具,第3章开始我们开始涉足语言基础,首先要彻底研究JavaScript中的函数(function),这可能会出乎大家意外之外。虽然你可能希望对象(object)是首先关注的内容,但object是对函数的深入理解,并且JavaScript是一种函数式语言,其可以让我们从普通的JavaScript程序员开始转变成JavaScript忍者!

第4章还是继续介绍函数,将把在第3章中学到的基础知识应用于我们在创建应用程序过程所面临的问题上。我们将探讨递归,不只是因为它本身的含义,而是因为我们可以通过检测递归学到更多关于函数的知识——我们将学习如何利用JavaScript的函数式编程特性让代码变得优雅,同时更加强大和简洁。我们将学习如何处理可变参数列表,以及在非原生支持方法重载的面向对象概念的语言中重载函数的方式。

第5章是大家可以从本书中学到的最重要概念之一的主题:闭包。函数式编程中的关键概念——闭包,允许我们对在程序中声明和创建的对象作用域进行细粒度控制。这些作用域的控制是JavaScript忍者编写代码的关键因素。即使不阅读本章后面的内容(但我们希望大家不要这样做),编程水平也会比刚开始学习时要好很多。

第6章解决对象问题,通过函数的prototype属性,我们可以学习创建对象的模式,我们将学习如何将对象绑定到它们定义的函数上——这是我们首先讨论函数的其中原因之一。

第7章主要是正则表达式,正则表达式是该语言常常被忽视的一项功能,如果正确使用,它可以完成很多行代码完成的工作。我们将学习如何构建并使用正则表达式,以及如何利用正则表达式及其相关方法优雅地解决一些反复出现的问题。

第二部分语言基础将在第8章结束,在本章我们将学习定时器和间隔定时器是如何在JavaScript的单线程特性中工作的。HTML5承诺使用Web workers为我们减少单线程限制,但大多数浏览器还无法做到,几乎所有现有的JavaScript代码都取决于对JavaScript单线程模型的深入理解。

第三部分从第9章开始,我们打开JavaScript运行时代码求值的黑盒子。我们来了解求值代码的各种方式,包括在我们的选择范围内怎样做是安全的。我们将讨论几个实例,比如JSON求值、元语言(又名领域特定语言)、压缩和混淆,甚至是面向方面编程。

在第10章中,我们将研究有争议的with声明,用于在作用域内缩短引用。无论你是with爱好者还是批评者,它都存在于大量的代码中,不管你认为它是炸弹还是令人憎恶的事物,都应该要理解它。

第11章的主题是处理跨浏览器问题。我们将研究5个与这些问题有关的关键开发问题:浏览器差异、错误和bug修复、外部代码和标记、缺失的功能以及回归。详细讨论特性模拟和对象检测等策略,以帮助我们应对这些跨浏览器挑战。

第12章的重点是处理元素特性(attribute)、属性(property)和样式(style)。虽然各种浏览器在如何处理这些元素方面的差异随着时间的过去会慢慢融合,但仍然有许多棘手的问题,本章将讲述如何解决这些问题。

第13章总结了第三部分内容,深入研究浏览器中的事件处理,以及创建能够以浏览器不可知方式处理事件的统一子系统方式。这包括给浏览器添加其无法提供的功能,如自定义事件和事件委托。

在第四部分中,我们加快进度,深入研究由jQuery等JavaScript库的核心内容引出的主题。第14章将讨论如何构建DOM操作API,在运行时操作文档对象模型,包括向DOM注入新元素的难题。

最后,在第15章中,我们将讨论如何构建CSS选择器引擎以及对选择器进行解析和求值的不同方式。这一章不适合胆小者,但可以用它来测验你是否能成为忍者。代码规范

清单或文本中的所有源代码都是采用固定宽度字体,将其与普通文本分离。文本中的方法和函数名、属性、XML元素和特性也采用相同的字体。

在某些情况下,原始源代码被重新格式化来适应页面。一般来说,编写原始代码时要考虑页面宽度限制,但有时你会发现本书中的代码和源下载提供的代码之间的格式有一点不同。在极少数情况下,不改变其意义,长长的代码行无法重新格式化,本书清单包含行接续符标记。

代码注释伴随有许多列表,用于突出重要概念。在许多情况下,数字编号对应着文本中的解释。源码下载

本书中所有运行示例的源代码(以及一些从未进入文本的额外代码)可以在本书的网页www.manning.com/SecretsoftheJavaScriptNinja上下载。

本书的代码示例按章节分类,每一章有单独的文件夹。布局由本地Web服务器来完成,如Apache HTTP服务器。简单将下载的代码解压缩到所选择的文件夹,并将该文件夹设置成为应用程序的根目录。

除了少数例外,大多数例子都不需要使用Web服务器,可以直接加载到浏览器中执行。

所有的例子都在各种现代浏览器中测试过(2012年中期),包括Internet Explorer 9、Firefox、Safari和Google Chrome。在线交流

作者和Manning出版社邀请你访问Manning出版社运营的本书论坛,在那里你可以评论本书,询问技术问题,并获得作者和其他用户的帮助。访问和订阅论坛,在浏览器中登录www.manning.com/SecretsoftheJavaScriptNinja,然后单击作者在线链接。这个页面提供有关如何注册登录论坛、可以获得哪些帮助以及论坛行为规则的信息。

Manning的承诺,是为读者提供一个场所,让各位读者以及读者和作者之间进行有意义的交流。Manning不要求作者的参与次数,对本书论坛的贡献仍是自愿的(无报酬)。我们建议大家试着询问作者一些具有挑战性的问题,以免他们转移兴趣!

只要本书在发售,在线交流论坛和先前讨论的帖子都可以在出版商的网站上进行访问。关于封面插图

本书封面上的图像是“能乐剧演员,武士”,19世纪中期一位不知名的日本艺术家制作的木刻版画。Noh(能乐剧)衍生自日语:天赋或技能,是从14世纪就开始出现的一种经典音乐剧。许多人物都戴着面具,男性扮演男性和女性角色。日本数百年来的英雄人物、武士,经常出现在表演中。在该版画中,精致的服装和威武的武士展示了这位艺术家的精湛技术。

武士和忍者都是日本艺术作品中善于打斗的勇士,他们非常勇敢和精明。武士是精英士兵,受过良好教育,文武双全,武士道是他们必须严格遵守的原则,自10世纪开始代代相传。他们来自贵族和上层阶级,相当于欧洲骑士。战争时,大批武士穿着精致的盔甲和彩色的服装,震慑住对方。忍者是靠武术技能选出,而不是社会地位或教育。他们穿着黑色服装,蒙面,单独或一小组出动,以诡计和隐身攻击敌人,千方百计完成任务,他们唯一的编码是保密的。

封面插图是由Manning的一位编辑多年来收集到的三个日本人物版画中的一个,当我们在为本书寻找忍者封面时,这幅引人注目的武士版画受到了我们的关注,它的细节刻画得很精致,色彩鲜明,生动地描绘了一位威武的战士志在必得的情形。

有时候我们很难区分两本计算机图书,Manning非常有创意,用200年前的插图做计算机图书的封面,这些插图描绘了世界各地的丰富多样的传统服装,印刷在封面上为其重新带来活力。第一部分 准入训练

本书的这部分内容将奠定JavaScript忍者训练的基础。

在第1章中,大家将了解阅读本书后我们要做到什么,以及JavaScript开发人员要操作的框架环境。

第2章讲述测试为什么如此重要,并提供对一些可用测试工具的简单调查。然后我们会开发一些令人叫绝的简单测试工具,从而在余下的阅读培训中进行使用。

阅读完这部分内容后,你将可以开始准备训练成为一名JavaScript忍者了!第1章 进入忍者世界

本章涵盖以下内容:● 介绍本书的目的和结构● 将要关注的库● 什么才是JavaScript高级编程● 跨浏览器编程● 测试套件示例

如果你正在阅读本书,应该知道,没有什么简单方法可以创建有效且跨浏览器的JavaScript 代码,除了编写整洁代码的常规挑战外,我们还要额外应对各种浏览器的差异和复杂性。为了应对这些挑战,JavaScript开发人员通常使用JavaScript库来实现通用和可重用的功能。

这些库虽然在方法、内容和复杂性方面有很大差异,但唯一不变的是:它们都需要简单易用,产生最少的开销,并能兼容所有浏览器,这些都是我们所希望的。

显而易见,通过了解如何构建最优秀的JavaScript库,可以为我们提供很好的洞察力,从而编写自己的代码来实现这些目标。本书力图揭示这些世界级代码所使用的技术和秘密,并将之聚集成一个单一的资源。

通过本书,我们将研究创建这些流行JavaScript库所使用(或即将使用)的技术。让我们开始了解这些库!1.1 即将探索的JavaScript库

创建现代JavaScript库所用到的技术和实践是我们在本书中所关注的焦点。我们要选择一个最重要的库,当然就是jQuery,其已经跃升为目前最普遍使用的JavaScript库了。

jQuery(http://jquery.com)由John Resig创建,并在2006年1月发布。jQuery将用于匹配DOM内容的CSS选择器进行了普及。在众多功能中,它还提供了DOM操作、Ajax、事件处理以及动画功能。

jQuery已经主导了JavaScript库的市场,它被用于成千上万的网站,数以百万计的用户与之交互。通过大量的使用和反馈,该库一直在精练——继续优化——成为目前我们正在使用的最优代码。

除了研究jQuery示例代码以外,我们也会了解以下库所利用的技术。● Prototype(http://prototypejs.org/)——现代JavaScript库之父,

Sam Stephenson于2005年创建并发布。除了面向对象编程、面

向切面编程以及函数式编程技术以外,该库还包含了DOM、

Ajax和事件功能。● Yahoo!UI(http://developer.yahoo.com/yui)——雅虎内部

JavaScript框架发展的结果,在2006年2月向公众发布。除了一

些预先定义的部件(日历、网格、手风琴等)以外,Yahoo !

UI(YUI)还包括DOM、Ajax、事件以及动画功能。● base2(http://code.google.com/p/base2)——由Dean Edwards

创建,于2007年3月发布。该库支持DOM和事件功能。它的闻名

之处在于它尝试以通用且跨浏览器的方式实现各种W3C规范。

这些库都经过了全面的构建并且解决了目标问题。基于这些原因,这些库对于我们进一步分析并理解代码库的基础建设,从而洞察世界级JavaScript库建设的过程打下了良好的基础。

但是这些技术,并不只用于构建大型库;它们也可以应用于所有的JavaScript代码,且无论代码大小。

一个JavaScript库的组成可以分为如下三个方面。● JavaScript语言的高级使用。● 跨浏览器代码的精心构建。● 当前能够聚众合一的最佳实践应用。

针对每个库,我们会仔细分析这三个方面,从而收集整理完整的知识体系,以便创建自己的高效JavaScript代码。1.2 理解JavaScript语言

很多JavaScript程序员,在工作中不断进步,直到能够熟练使用大量的JavaScript语言元素,包括对象、函数(如果他们始终关注编码趋势)甚至是匿名内联函数。然而,在许多情况下,这些技巧可能并没有超出基础水平。此外,这些程序员,通常对JavaScript中闭包(closures)的目的和实现有着非常匮乏的理解,而闭包从根本上例证了函数对于该语言的重要性。

JavaScript中,对象、函数和闭包之间有着很密切的关系(如图1.1所示)。理解这三个概念之间的牢固关系,可以大大提高我们的JavaScript编程能力,为我们进行任意类型程序的开发打下坚实的基础。图1.1 JavaScript中,对象、函数和闭包之间的密切关系

很多JavaScript开发人员,尤其是有面向对象背景的开发人员,可能会更多地关注对象,但却没有了解函数和闭包对于整个程序的作用。

除了这些基本概念,还有两个JavaScript特性远远未被充分利用:定时器和正则表达式。这两个概念,几乎在任何程序的JavaScript代码中都有,但由于易于被误解,因此它们并没有发挥全部潜力。

熟练掌握定时器如何在浏览器内运行(通常很神秘的),可以让我们有能力解决复杂的编码任务,如长时间运行的计算和平滑的动画。而理解正则表达式是如何工作的,可以让我们简化原本相当复杂的代码段。

作为JavaScript语言之旅的另一个高潮,我们将研究第10章中的with语句,以及第9章中有争议的eval()方法——两个重要但是具有争议的语言特性,这两个特性已经被滥用、误用,甚至有很多JavaScript程序员对其怨声载道。注意:持续关注Web开发技术发展趋势的人会知道这两个主题

是有争议的,在未来版本的JavaScript中会被弃用或者被限

制使用。但由于在现有代码中可能会遇到这些概念,所以即使在

将来的代码中不使用它们,理解它们也是非常重要的。

观察一些高级JavaScript程序员的工作,我们将会看到,恰当使用一些高级语言特性可以创建一些神奇的代码片段,而其他方式则往往不太可能。在很大程度上,这些高级特性也可以用于一些有趣的元编程练习,将JavaScript代码编写成任意我们想要的。

学习如何高效使用高级语言特性,以及如何发挥其最大优势,将代码质量提升到更高的水平。提升我们运用这些概念和特性的能力,提高我们的理解力,熟练掌握如何创建任意类型的JavaScript应用程序。这些基础知识,将为我们开始编写稳定跨浏览器代码的道路奠定坚实的基础。1.3 跨浏览器注意事项

完善JavaScript编程技能将引导我们不断前行,尤其是目前,除了浏览器端以外,JavaScript还能够使用Rhino、V8或Node.js库等JavaScript引擎在服务器端运行。但开发基于浏览器的JavaScript应用程序(这也是本书的重点)时,越早越好的是,我们首先要应对:浏览器及其令人恼火的问题和矛盾。

理想世界中,所有的浏览器中都没有bug,并且支持以一致的方式支持Web标准,但是我们都知道我们并不生活在这种世界里。

近来浏览器的质量已经有了大大改善,但仍有一些bug、缺失的API和不同浏览器的特定缺陷,我们需要解决这些问题。制定解决这些浏览器问题的综合性策略并熟悉不同浏览器之间的区别和缺陷,和精通JavaScript本身同等重要。

对于这些差异,在编写浏览器应用程序或JavaScript库时,决定支持哪些浏览器是一个重要考虑事项。我们可能想支持所有的浏览器,但却受限于开发和测试的资源限制。那么,我们如何决定支持哪些浏览器,支持到什么程度?

有一个方法,是来自古老Yahoo!的一个松耦合方式,称为分级浏览器支持(graded browser support)。在这种技术中,我们创建一个浏览器支持矩阵,作为记录浏览器和其平台的重要性的快照。

在这样一个表格中,我们在一个轴上列出目标平台,在另外一个轴上列出浏览器。然后,在每个单元格中,对每个浏览器/平台组合,我们给出一个“等级”(从A到F,或者是其他能够满足我们需要的评分系统)。表1.1展示了一个这样的例子。

注意,我们还没有填写任何等级。如何对特定平台和浏览器分配等级,完全取决于项目的需要和需求,以及其他重要的因素,例如目标受众的组成。使用这种方式,我们制定出相应平台/浏览器重要性的等级,并将这些信息和成本进行结合,尝试找出最优化的浏览器支持。我们将在第11章更深入地探索这些内容。表1.1 一个假设的“浏览器支持矩阵”WindowsOS XLinuxiOSAndroidIE 6N/AN/AN/AN/AIE 7,8N/AN/AN/AN/AIE 9N/AN/AN/AN/AFirefoxN/AChromeSafariN/AN/AOpera

由于支持大部分的平台和浏览器组合是不切实际的,因此我们必须权衡支持各种浏览器的成本与收益。任何类似的分析,都必须要考虑多个因素,主要有如下几点。● 目标受众的期望和需求。● 浏览器的市场份额。● 支持该浏览器所需的工作量。

第一点是主观的,只有具体项目才能够确定。第二点是市场份额,可以通过互联网信息得到。支持每个浏览器的工作量,可以通过考虑该浏览器的功能和对现代浏览器标准的遵守情况进行粗略估计。

图1.2所示的图表,展示了主流浏览器的使用情况(信息来自2012年8月的StatCounter)以及我们对排名靠前的桌面浏览器开发成本的个人建议。图1.2 各种桌面浏览器的支持成本与收益分析,揭示了我们要努力的方向

图表以“收益”与“成本”的方式进行展示,大概一看就可以知道怎么做“最划算”。跳出该图表,如下还有几点要注意的事项。● 尽管与标准兼容的浏览器相比,支持IE 7和IE 8需要更多的工作

量,但它们仍然有很大的市场份额,如果这些用户是我们程序的

一个重要目标观众,那么这些额外的工作就是值得的。● IE 9,在标准兼容性方面取得明显进展,与之前的IE版本相比更

容易得到支持,并已经取得了一定的市场份额。● 支持Firefox和Chrome是显而易见的,因为它们有很大的市场份

额,并且很容易支持。● 尽管Safari浏览器的市场份额相对较低,它仍然值得支持,因为

它符合标准的特性使得其支持成本很小(作为一个经验法则,如

果能在Chrome浏览器下使用,那也就能在Safari下使用——尽管

是在推理情况下)。● Opera,虽然需要的工作量比Safari还少,但因为它的市场份额

很小,所以可以从桌面浏览器市场上忽略它。但如果移动平台对

你来说很重要,移动版的Opera则可以发挥更大的作用,如图1.3

所示。图1.3 移动市场,开发成本和收益相当,实际源于统计数据● 对于IE 6,真的没什么可说的了。(参见

www.ie6countdown.com。)

看一下移动市场,情况就完全不同了,如图1.3所示。

当然,任何事情都不是那么枯燥。也许更恰当的说法是,好处比成本更重要,但这最终要看决策者的选择,他们要考虑市场需求和其他业务问题等因素来制定决策。但量化成本和收益是做出这些重要支持决策的一个良好起点。

另外,要注意,市场份额和支持成本的变化是很迅速的。密切关注像http://gs.statcounter.com这样的网站不失为一个明智的预防措施。

资源受限组织的另一个潜在因素是开发团队的技能。开发应用程序的主要原因就是让最终用户使用,开发人员可能需要发展必要的技能来开发该应用程序,以满足最终用户的需求。在成本分析阶段就需要考虑这些因素。

跨浏览器开发的成本,主要取决于开发人员的技能和经验,而本书的目的就是提高开发人员的技术水平,所以让我们首先来看一下当前的最佳实践。1.4 当前最佳实践

掌握JavaScript语言和跨浏览器编码问题是成为Web应用程序开发专家的重要条件,但它们并不是全部。要进军专家行列,还需要秀出以下很多开发人员之前都已经掌握的高质量代码。我们将在第2章深入研究这些被称为最佳实践(best practices)的特征,除了熟练掌握语言外,还包括如下元素。● 测试。● 性能分析。● 调试技巧。

在我们的编程过程中,时常遵守这些最佳实践是极其重要的;跨浏览器开发的复杂性也直接证明了这一点。让我们来看看这些实践。1.4.1 当前最佳实践:测试

在本书中,我们将使用大量的测试技术,以确保示例代码的运行符合我们的预期,同样也作为测试一般代码的示例。对于测试,我们将使用的一个主要工具是assert()函数,其目的是断言代码是true还是false。

该函数的一般形式是:

第一个参数是一个条件,应该是true,而第二个参数则是一个消息,在第一个参数不为true时进行显示。

考虑如下代码:

如果变量a的值不等于1,断言就会失败,这些过于戏剧性的消息就会显示。

注意,assert()函数并不是JavaScript语言的原生特性(一些像Java这样的语言,也提供这样的功能),所以我们会自己实现它。我们将在第2章讨论assert()函数的实现以及使用。1.4.2 当前最佳实践:性能分析

另一个重要的实践是性能分析。浏览器的JavaScript引擎在JavaScript本身的性能表现上取得了惊人的进步,但这并不是我们编写劣质和低效代码的借口。

我们将使用本书稍后的如下代码,收集性能信息:

上述代码中,我们在代码执行的地方记录时间戳:一个在代码执行开始前,一个在代码执行后。两个时间戳之间的差值告诉我们代码执行了多少时间,使用相同的方式,我们可以测量其他替代代码方案的执行时间。

注意我们是如何多次执行代码的;在本例中,我们执行的次数由maxCount表示。因为代码的单次操作执行太快而很难准确地测量,所以我们需要多次执行代码以获取可衡量的值。至于执行次数有多频繁,这个数可以是成千上万,甚至上百万,这取决于被测代码的性质。通过反复试验,我们可以选择一个合理的值。

这些最佳实践技术,以及在这个过程中我们将学到的其他实践,将极大地提高我们的JavaScript开发水平。用浏览器提供的有限资源开发应用程序,再加上浏览器功能和兼容性问题的日益复杂,因此掌握完整和强大的技能是非常必要的。1.5 总结

以下是我们在本章所学到的内容。● 跨浏览器的Web应用程序开发是困难的,比大多数人想象的都要

难。● 为了圆满完成跨浏览器开发,我们不仅要掌握JavaScript语言,

还要全面了解浏览器以及它们的怪异模式和矛盾,并要具备当前

最佳实践方面的良好基础。● JavaScript开发毋庸置疑是很具有挑战性的,但有一些勇敢者已

经沿着这条曲折的道路走了下来,那就是JavaScript库的开发

者。我们将提炼这些代码库中的知识,有效地提高我们的开发技

能,并将这些技能提升到世界一流水平。

这些探索肯定会很有益且具有教育意义——让我们来享受这个过程吧!第2章 利用测试和调试武装自己

本章涵盖以下内容。● JavaScript代码调试工具● 测试用例生成技术● 构建测试套集● 如何测试异步操作

为代码构建有效的测试套件是非常重要的,所以在我们进入任何编码之前,要首先对它进行讨论。和可靠的测试策略同样重要的是要对所有代码进行测试,外部因素有可能影响代码的操作效果这点十分重要,这正是我们在跨浏览器JavaScript开发时要面对的情况。

我们不仅要处理典型问题:确保代码质量,尤其是与多位同时编写一段代码的开发人员打交道时,并避免出现会破坏API的回归错误(所有程序员都需要处理的普通问题),还要处理:判断代码是否在我们选择支持的所有浏览器上都能正常运行。

在讨论第11章的跨浏览器策略时,我们将进一步深入讨论跨浏览器开发问题,但是现在,重要的是要强调测试的重要性和测试策略的定义,因为我们将在本书的剩余部分使用这些策略。

在本章中,我们将了解用于调试JavaScript代码的一些工具和技术,并基于这些结果生成测试用例,并构建测试套件,从而可靠地运行这些测试。让我们开始学习吧。2.1 调试代码

还记得调试JavaScript的时候要使用alert()来验证变量的值吗?不过,在过去几年里,调试JavaScript代码的能力已经得到了大大的改善,在很大程度上是因为Firefox上的Firebug开发扩展的普及。

所有主流浏览器都有类似的工具。● Firebug——流行的Firefox开发者扩展,越来越好。详情查看

http://getfirebug.org/。● IE开发者工具——存在于IE 8及以后版本。● Opera Dragonfly——存在于Opera 9.5及以后版本。也适用于移

动版Opera。● WebKit开发者工具——首次出现在Safari 3中,在Safari 4中得到

显著改善,现在也能用在Chrome中。

调试JavaScript有两个重要的方法:日志记录和断点。它们可以回答下面这个重要的问题(“我的代码发生了什么事?”),但两种方法是从不同的角度来解决这个问题的。让我们先看一下日志记录。2.1.1 日志记录

日志记录(logging)语句(如,在Firebug、Safari、Chrome以及新版本Opera中使用的console.log()方法)是代码的一部分(即使可能是暂时的),并且在跨浏览器场景上十分有用。我们可以在代码中记录日志,并且可以从所有现代浏览器的控制台上看到的日志消息中获益。

相对于古老的“添加alert函数”这种技术,这些浏览器控制台都极大地改进了日志记录过程。在不阻碍程序正常处理过程的情况下,所有的日志记录语句都能写入到控制台,并能立即或稍后获得显示——而有些事情是alert()函数无法做到的。

例如,如果我们想知道变量x在代码特定位置的值是什么?我们可能会这样写:

在启用了JavaScript控制台的Chrome浏览器上,上述代码的执行结果如图2.1所示。图2.1 日志可以让我们看到代码在运行时的状态

在记录日志时,老版本的Opera实现了一个postError()属性方法。如果必须要在这些旧版浏览器中记录日志,我们可以采用温和、更高级别的日志记录方法,适用于所有的浏览器,代码如下所示。注:如果不需要处理过时版本的Opera,可以忽略这些

代码,放心地使用console.log()。

代码清单2.1 一个适用于所有现代浏览器的简单日志记录方法提示:欲了解更多内容信息,可以访问http://patik.com/blog/

complete-cross-browser-console-log/查看代码清单2.1的更全

面版本。

在代码清单2.1中,我们首先尝试使用绝大多数现代浏览器都能用的console.log()方法记录日志消息,如果失败,将会抛出一个异常,然后我们捕获该异常,继而再尝试使用Opera的专有方法记录该日志消息。如果这些方法都失败了,我们重新回来使用古老的alert函数。注意:代码清单2.1使用了JavaScript Function()构造器的

apply()和call()方法接收传递的参数进行日志记录。

Function()的这些方法用于帮助我们进行精确控制JavaScript

函数的调用,在第3章,我们将会看到更多相关内容。

在代码运行时,通过记录日志查看程序运行状态是很好的做法,但有时我们要暂停代码的运行,并需要查看一下此时的相关信息。

这就是断点要做的。2.1.2 断点

断点(breakpoint)是一个比日志记录更复杂的概念,但它比日志有一个更显著的优势:它能在特定的代码上暂停脚本的执行,从而暂停浏览器运行。这使得我们可以在该断点处,随意查看任意代码的状态。其中包括所有可访问的变量、上下文以及作用域链。

如下所示,假设有一个页面,使用我们的新log()方法记录日志。

代码清单2.2 使用自定义log()方法的简单页面

如果我们使用Firebug在代码清单2.2的注释行设置一个断点(在脚本显示的行号上进行单击),刷新页面重新执行代码,调试器就会在这一行停止执行,并向我们展示图2.2所示的效果。图2.2 断点允许我们在特定代码上暂停执行,从而查看此时的状态

注意,右边的窗格允许我们查看代码运行的状态,包括x的值。调试器会在实际要执行的断点前暂停执行;在本例中,log()方法还没有被执行。

如果我们想使用新方法进行调试,可以单步执行该方法,一探究竟。单击“进入(step into)”按钮(最左边的黄金箭头按钮)可以让调试器开始执行新方法的第一行,然后我们会看到图2.3所示的内容。注意显示的状态已经改变,从而让我们可以查看log()方法执行的新状态。图2.3 单步执行该方法,可以让我们看到代码执行的新状态

任何具有断点功能的全功能调试器都高度依赖于执行该调试器的浏览器环境。鉴于这个原因,上述开发者工具才会被创建;否则,它们的功能也不会实现。这是一个对整个Web开发社区的伟大贡献和救济,所有主流的浏览器实现者都可以创建有效的实用工具程序以便调试。

调试代码不仅符合其主要和明显目的(检测并修复bug),而且也可以帮助我们获取当前生成高效测试用例的最佳实践。2.2 测试用例生成

Robert Frost曾写道:篱笆筑得牢,邻居处得好,Web应用程序也是如此,不管是何种编程准则,好的测试铸就好的代码。注意对这个“好”字的强调。如果测试用例的构建很差,它很有可能只是大量的测试套件,不会真正帮助我们提高代码质量。

优秀的测试用例具有三个重要特征。● 可重用性(repeatability)——测试结果应该是高度可再生的。

多次运行测试应该产生相同的结果。如果测试结果是不确定的,

那我们又如何知道哪些结果是有效的,哪些又是无效的呢?此

外,可重现性可以确保我们的测试不依赖于外部因素(诸如网络

或CPU负载)。● 简单性(simplicity)——测试应该只专注于测试一件事。在不影

响测试用例目的情况下,我们应该尽可能消除过多的HTML标记、

CSS或JavaScript。我们删除得越多,测试用例只受特定代码影

响的可能性就越大。● 独立性(independence)——测试用例应该独立执行。我们必

须避免一个测试结果依赖于另外一个测试结果。把测试分解成尽

可能小的单元,这将帮助我们确定在错误发生时的确切代码位

置。

有很多方法可以用于构建测试,有两种主要的方法分别是解构型测试和构建型测试:

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载