爱问 爱问共享资料 爱问分类
首页 > > > javascript面向对象编程.pdf

javascript面向对象编程.pdf

javascript面向对象编程.pdf

上传者: weidong1365381
1152次下载 0人收藏 暂无简介 简介 2011-09-14 举报

简介:javascript教程,都非常经典

1第一部分:现代JavaScript简介第一章现代JavaScript编程JavaScript的演化是渐进而稳固的。历经过去十年的进程,JavaScript在人们的认知里已经从一门简单的玩物式的语言逐渐发展成为一门倍受推崇的编程语言,被全世界的公司和开发者用来构造种种精彩的应用。现代JavaScript编程语言一如既往地可靠、健壮,强大得令人难以置信。在本书中我进行的许多论述,将揭示是什么使得现代JavaScript应用程序与从前有着那么明显的不同。本章中出现的许多概念远不能算新奇,然而成千上万聪明的程序员的认同促使它们的用途得以升华并最终形成今天的格局。既如此,我们这就来着眼现代JavaScript程序设计。面向对象的JavaScript从语言的视角来看,面向对象的程序设计和面向对象的JavaScript语言绝对不是什么摩登的东西;JavaScript最开始就是被设计成一种彻底的面向对象语言。然而,随着JavaScript在其使用和接受的过程中的“逐步发展”,其它语言(如Ruby,Python,和Perl等)的程序员留意到了它并开始将他们的编程模式引入了JavaScript。面向对象的JavaScript代码的外观和内部运作都有别于其它具有对象能力的语言。在第二章我将深入论述使它如此独特的方方面面,而在这里,先来看一点基础的东西以体会编写现代JavaScript代码的初步感觉。程序1-1中的两个对象构造器的例子,演示了可用于学校课程的简单的对象搭配。程序1-1.课程和课程表的面向对象JavaScript表述CODE://类Lecture的构造器//使用两个字符串参数,name和teacherfunctionLecture(name,teacher){//把它们作为对象的本地属性保存this.name=name;this.teacher=teacher;}//类Lecture的方法,生成一个显示该课程信息的字符串Lecture.prototype.display=function(){returnthis.teacher+"isteaching"+this.name;};//类Schedule的构造器//使用一个lectures类型的数组作为参数PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn2functionSchedule(lectures){this.lectures=lectures;}//类Schedule的方法,用来构造一个描述该课程表的字符串Schedule.prototype.display=function(){varstr="";//遍历每门课程,累加构成信息字符串for(vari=0;i<this.lectures.length;i++)str+=this.lectures[i].display()+"";returnstr;};从程序1-1的代码中你或许已经看出,大部分的面向对象基本原则贯穿存在于其中,但它们是以不同于其它更常见的面向对象语言的方式组织起来的。你可以创建对象构造器和方法,并存取对象属性。程序1-2展示了在应用程序中使用上面两个类的一个示例。程序1-2.给用户提供课程的列表CODE://创建一个新的课表对象,存于变量mySchedule中varmySchedule=newSchedule([//创建一个课程对象的数组,//作为传给课表(原文此处为Lecture,疑为笔误)对象的唯一参数newLecture("Gym","Mr.Smith"),newLecture("Math","Mrs.Jones"),newLecture("English","TBD")]);//弹出对话框显示课表的信息alert(mySchedule.display());伴随对广大程序员对JavaScript的接受,设计良好的面向对象代码的使用也正日益普及。贯穿本书的始末,我将试图展示我认为能够最好地例示代码设计与实现的不同的面向对象的JavaScript代码片段。测试你的代码建立起良好的面向对象的基本代码之后,开发专业品质的JavaScript代码的第二个方面是确保拥有一个强劲的代码测试环境。当开发频繁使用的或将由其它开发者维护的代码时,严格调试的必要性会显得尤为突出。为其它开发者提供一个坚实的测试基础,是维持代码开发活动的关键。在第四章,你将会看到一些可用来形成良好的测试/使用框架的不同工具,以及对复杂应用程序的简单调试。用于Firefox的插件Firebug就是其中一例。Firebug提供了许多的有PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn3用的工具,如错误控制台,HTTP请求日志,调试,以及元素查看。图1-1展示了Firebug调试一段代码时的实况截屏。图1-1.FirefoxFirebug插件运行时的截屏开发干净的、可测试的代码的重要性怎么强调都不会过分。一旦你开始开发一些干净的面向对象代码并将它们与合适的测试套件结合,相信你会倾向于同意这一点。为分发而进行的封装开发现代的专业JavaScript代码的最后一个方面是为了代码分发或在现实世界里中使用而进行的封装处理。随着开始开发者们在其页面中使用越来越多的JavaScript代码,冲突的可能性将会增加。如果两个JavaScript库里都有一个名为data的变量或者按各的意图添加事件,灾难性的冲突和莫名其妙的错误可能就会出现。开发者简单地置入<script>指针无须任何变动就能正常工作的能力是开发一个成功的JavaScript库的精诣所在。开发者用以保持代码清洁和普遍兼容的的技术或解决方案有许多种。使用命名空间是广泛使用的保证代码不与其它JavaScript代码互相影响和抵触的一种技术。这方面一个极端的(但未必是最好或最有用的)运作中的例子就是Yahoo开发的任何人都可使用的用户界面库。使用该库的一个示例见程序1-3.程序1-3.使用重度名称空间化的YahooUI库给一个元素添加事件CODE://给ID为"body"的元素添加mouseover事件监听器YAHOO.util.Event.addListener('body','mouseover',function(){//andchangethebackgroundcoloroftheelementtoredthis.style.backgroundColor='red';});然而,这种命名空间方法存在一个问题,即库与库之间在构造和使用的方式上缺乏内在PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn4的一致性。正是在这一点上,中心代码仓库如JSAN(JavaScriptArchiveNetwork)变得非常有用。JSAN提供一套代码库需遵从的一致规则,以及一种快捷导入代码所依赖的其它库的方式。图1-2展示了JSAN的主分发中心的一个截屏。图1-2.公共代码仓库JSAN的截屏我将在第三章阐述开发清洁的可封装代码的细节。此外,其它常见的事故多发点如事件处理冲突,将在第六章论述。UnobtrusiveDOM脚本编程(非侵入的DOM脚本编程)基于一个优良的可测试的核心创建你的代码和兼容的分发,是UnobtrusiveDOM脚本编程的基本概念。编写unobtrusive代码意味着与你的HTML内容的彻底分离:数据来自服务器,而JavaScript代码用来使其动态化。达到这一彻底分离的最重要的副作用就是你的代码在不同的浏览器之间可以完美的升/降级。利用这一点,你可以提供高级的内容给支持它的浏览器,而在不支持的浏览器上从容隐藏之。编写现代的、Unobtrusive代码包括两个方面:文档对象模型(DOM)和JavaScript事件。本书中我对这两个方面都将作深入的解释。PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn5文档对象模型DOM是表示XML文档的流行的方法。它未必是最快的、最轻便的、或者最易使用的,却是是最普及的,绝大多数web开发语言(如Java,Perl,PHP,Ruby,Python,及Javascript)都实现了对它的支持。DOM旨在为开发者提供一种直观的方式来导航于XML的层次结构中。因为有效的HTML只是XML的一个子集,保有一个方式来有效地解析和浏览DOM文档对于简化JavaScript开发来说是必不可少的。从根本上讲,出现在JavaScript中的大多数的交互是发生在JavaScript与页面所包含的不同HTML元素之间的;DOM是使这此过程简单化的卓越工具。程序1-4展示了使用DOM在页内导航和查找不同的元素然后操作它们的一些例子。程序1-4.使用文档对象模型定位并操纵不同的DOM元素[Copytoclipboard][-]CODE:<html><head><title>IntroductiontotheDOM</title><script>//直到文档完全载入,我们才能操作DOMwindow.onload=function(){//找到文档中所有的<li>元素varli=document.getElementsByTagName("li");//然后给它们全部加上边框for(varj=0;j<li.length;j++){li[j].style.border="1pxsolid#000";}//定位ID为'everywhere'的元素varevery=document.getElementById("everywhere");//并将它从文档中移除every.parentNode.removeChild(every);};</script></head><body><h1>IntroductiontotheDOM</h1><pclass="test">ThereareanumberofreasonswhytheDOMisawesome,herearesome:</p><ul><liid="everywhere">Itcanbefoundeverywhere.</li><liclass="test">It'seasytouse.</li><liclass="test">Itcanhelpyoutofindwhatyouwant,PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn6reallyquickly.</li></ul></body></html>DOM是开发UnobtrusiveJavaScript代码的第一步。借助简单快速导航HTML文档的能力,所有随之而来的JavaScript/HTML交互将变得如此简单。事件事件将一个应用程序之内所有的用户交互结合在一起。在一个设计良好的JavaScript应用程序里,你将拥有数据源和它的视觉的表示(在HTMLDOM内部)。为了同步这两个方面,你必须监视用户的交互动作并试图相应地更新用户界面。使用DOM和JavaScript事件的结合是使得现代web应用程序赖以工作的基本组合。所有的现代浏览器都提供一系列的只要特定交互动作发生即被触发的事件,如用户移动鼠标,敲击键盘,或离开页面等等。使用这些事件,你可以注册代码到特定事件,一旦该事件发生,你的代码就会被执行。程序1-5展示了这种交互的一个实例,该网页中的<li>元素在用户鼠标经过的时候会改变背景色。程序1-5.使用DOM和事件来提供一些视觉效果[Copytoclipboard][-]CODE:<html><head><title>IntroductiontotheDOM</title><script>//直到文档完全载入,我们才能操作DOMwindow.onload=function(){//查找所有的<li>元素,附以事件处理程序varli=document.getElementsByTagName("li");for(vari=0;i<li.length;i++){//将鼠标移入事件处理程序附在<li>元素上,//该程序改变<li>背景颜色为蓝色li[i].onmouseover=function(){this.style.backgroundColor='blue';};//将鼠标移出事件处理程序附在<li>元素上,//该程序将<li>的背景颜色改回白色li[i].onmouseout=function(){this.style.backgroundColor='white';};}PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn7};</script></head><body><h1>IntroductiontotheDOM</h1><pclass="test">ThereareanumberofreasonswhytheDOMisawesome,herearesome:</p><ul><liid="everywhere">Itcanbefoundeverywhere.</li><liclass="test">It'seasytouse.</li><liclass="test">Itcanhelpyoutofindwhatyouwant,reallyquickly.</li></ul></body></html>JavaScript事件是复杂多样的。本书中的大多数代码或应用程序都以某种方式利用了事件。第六章和附属B完全专注于事件及其交互。JavaScript与CSS动态HTML建立在DOM和事件交互的基础上。在核心层面上,动态HTML表示发生在JavaScript和附着在DOM元素上的CSS信息的交互。层叠式样式表(CSS)作为布局的标准服务于简单的不唐突的网页,在最小化了用户端兼容性问题的同时,提供给开发者以强大的可控制性。从根本上讲,动态HTML就是探索JavaScript和CSS彼此交互作用时能够达到什么以及怎样最好地利用该联合达成令人印象深刻的效果。更高级的交互示例如拖放元素和动画效果见第七章。在那里我将围绕它们展开深入论述。AjaxAjax,或曰异步Javascript与XML,是由AdaptivePath公司的创办人之一兼董事长JesseJamesGarrett在其论文"Ajax:Web应用程序的新途径"(http://www.adaptivepath.com/publ...archives/000385.php)中创造的一个术语。它描述了请求和提交额外的信息时发生于客户和服务器之间的高级交互。术语Ajax包括了许多种数据据通讯的可能组合,但它们都围绕一个中心前提:附加的数据请求是在页面完全载入之后由客户端向服务器发起的。这允许应用程序开发者超越缓慢的、传统的应用程序流程,创建与用户相关的额外交互。图1-3是来自Garrett的Ajax论文的一个图示,说明了应用程序中由于额外的请求发生在后台(而且用户很可能并不知情),交互的流程发生了怎样的改变。PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn8图1-3:来自文章"Ajax:Web应用程序的新途径"的图示,展示发生于客户和服务器之间的先进的异步的交互Garrett论文的最初发表,激起了用户、开发者、设计者以及管理者们的兴趣,使用高级交互的新型应用程序爆炸式地增长。讽刺的是,在这一兴趣复苏的同时,Ajax背后的技术却是相当陈旧的(在2000年左右就有已有了商业上的应用)。然而最主要的不同在于,老的应用程序利用了浏览器特有的方式与服务器通讯(如仅ie具有的功能)。由于所有的现代浏览器都支持XMLHttpRequest(发送或从服务器接收数据的主要手段),theplayingfieldhasbeenleveled(见#12cfs178的回复),每个人都可以享受其益处。如果说有一个公司走在了利用Ajax技术创建优秀应用程序的最前列,那无疑是Google。恰在最初的Ajax论文出现之前,它发布了一个高交互性的domo:GoogleSuggest。该demo可以实时地自动完成你所键入的查询,这是旧式的页面重载不可能达到的功能。图1-4是GoogleSuggest运行时的一个截屏。PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn9图1-4.GoogleSuggest,早于Garrett的Ajax论文的利用了异步XML技术的应用程序除此而外,Google的另一个革命性的应用程序为GoogleMap,用户在其地图上移动将会实时地看到相关的局部结果。这一程序通过使用Ajax技术而提供的速度和可用性的水平是其它任何可用的地图程序所无法比拟的,结果彻底地变革了在线地图市场。图1-5是GoogleMap的截屏.图1-5.GoogleMaps,利用了一些Ajax技术来动态载入特定区域信息PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn10浏览器支持JavaScript开发所面临的不幸事实是,因为与实现和支持它的浏览器关联过于紧密,它受到当前最流行浏览器的支配。由于用户未必会使用对JavaScript支持得最好的浏览器,我们被迫对哪些是最重要的功能作出抉择。许多开发者已经开始做的是去掉对那些导致过多开发障碍的浏览器的支持。因为它们用户群的规模和还是因为它们拥有你喜欢的功能而考虑对浏览器的支持,需要仔细的权衡。最近Yahoo发布了一个可用来扩展你的web应用程序的JavaScript库。连同那个库,它还发布了一些供web开发者遵从的指导方针。以我之见,从中产生的最重要的文档是Yahoo支持与不支持的各种浏览器的官方的列表。尽管任何人或任何公司都可以做类似的事情,一份由互联上访问最频繁的网站所提供的文档,其价值绝对无法估量。Yahoo开发了一个分级的浏览器支持策略,对浏览器指定特定的级别并依据其功能为它提供不同的内容。Yahoo给浏览器三个级别:A,X和C:A级浏览器是得到完全支持和测试的,Yahoo的所有程序都能有保障在其中运行。X级浏览器是Yahoo认可但是没能彻底测试的准A级浏览器,或者是崭新的从未遇到过的浏览器。X级浏览器被期望能处理高级的内容,与A级浏览器等同对待。C级浏览器是已知的“劣质的”浏览器,不支持运行Yahoo应用程序所必须的功能。由于Yahoo应用程序完全Unobtrusive(即使没有JavaScript它们也能继续工作),这些浏览器只需处理不含JavaScript的功能性的内容。顺便一提,Yahoo的浏览器级别选择竟与我的不谋而合,这使得它尤其富有吸引力。在这本书里,我大量地使用了术语“现代浏览器”,当我用这一措词的时候,我指的Yahoo浏览器分级表评定为A级的任浏览器。给定一组赖以工作的一致的功能,减少因避免浏览器的不兼容而带来的痛苦,学习和开发的经历将会变得更加有趣。我极力推荐你们去通读浏览器分级的支持文档(见http://developer.yahoo.com/yui/articles/gbs/gbs.html,该文档包含了图1-6所示的浏览器支持表),感受一下Yahoo力图实现的是什么。通过将些信息公之于web开发的大众,Yahoo正在给出一条无价的“黄金标准”让其它所有人去靠拢,这是很了不起的。PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn11图1-6.Yahoo提供的浏览器分组支持表更多的关于浏览器支持情况的信息请参看本书的附录C,那里对每种浏览器的缺点和长处都有深入的论讨。或多或少地,你会发现所有的A级浏览器都走在发展的最前列,提供了远远超出你的开发所需要的功能。当选择你希望支持哪些浏览器时,最终结果实际上可以归结为你的应用程序支持的一组功能。如果你想要支持NS4或IE5(举个例子来说),则势必严格地限制你可以在程序中使用的功能的数量,因为它们缺乏对现代编程技术的支持。尽管如此,了解哪些浏览器是现代的允许你利用其中可用的强大的功能并给你一个可供将来的开发所依据的稳固的基础。这一稳固的开发基础可由以下几种功能所定义:核心Javascript1.5:最近、最广泛接受的JavaScript版本。它全面支持面向对象的JavaScript。IE5.0不支持全部的1.5,这是开发者们不愿意支持它的主要原因。XML文档对象模型(DOM)2:用来访问HTML和XML文档的的标准方案。这绝对是编写高效率的程序不可或缺的。XMLHttpRequest:Ajax技术的支柱——用来发起HTTP请求的一个简单层。所有的浏览器默认都支持这一对象,除了IE5.0-6.0;而它们也都支持用ActiveX初始化功能相当的对象。CSS:网页设计的基本需求。这似乎像是一个额外的需求,但是拥有CSS对web应用程序开发者来说是必不可少的。由于每一种现代浏览器都支持CSS,大多数问题的发生通常归结为呈现方面的差异。这正是IEforMac较少被频繁支持的主要原因。以上这些浏览器功能的结合构成了开发JavaScriptweb应用程序的支柱。所有的现代浏览器都以某种方式支持以上列举的功能。本书论述的所有内容都基于这一假设:你所使用的浏览器最起码能支持它们本章摘要本书试图完全包括所有现代、专业的JavaScript编程技术,以期它们被从独立开发者到大型公司的每一个人使用,使得其代码更加可用、可读、具有交互性。PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn12在这一章里我们对这本书里将会出现的每一个知识点做了一个简短的总览。这包括专业JavaScript编程的基础:编写面象对代码,测试代码,为分发而进行封装。随后你看到了UnobtrusiveDOM脚本编程的主要方面,包括一个关于文档对象模型,事件,JavaScript与CSS交互的简短的总览。最后你看到了Ajax背后的前提和在现代浏览器中JavaScript的支持。这些话题加在一起,足够带你步入专业级JavaScript程序员的行列。第二部分专业的JavaScript开发第二章面对对象的JavaScript对象是JavaScript的基本单位。实际上JavaScript中一切都是对象并得益于这一事实。然而,为了增强这一纯粹的面向对象的语言,JavaScript包括了一个庞大的功能集,使它无论是在潜在能力还是风格上,都成为一门极其独特的语言。本章中我将开始覆盖JavaScript语言的最重要的一些方面,如引用,作用域,闭包,以及上下文,你会发现这正是其它JavaScript书籍中很少论及的。打下主要的基础以后,我们将开始探索面向对象JavaScript的几个重点,包括对象到底如何运作和怎样创建新的对象并在特定的许可条件下设置其方法。如果你认真去读的话,这很可能是本书中最重要的一章,它将彻底地改变你看待JavaScript作为一门编程语言的方式。语言特性引用JavaScript的一个重要的方面是引用的概念。引用就是指向对象实际位置的指针。这是一项极其强大的功能。前提是,实际的对象决不是一个引用:字符串总是一个字符串,数组总是一个数组。然而,多个变量可以引用相同的对象。JavaScript就是以这种引用引用机制为基础。通过维护一系列的指向其它对象的引用,语言为你提供了更大的弹性。另外,对象能包括一系列的属性,这些属性简单地引用其它对象(如字符串,数字,数组等等)。当几个变量指向相同对象时,修改底层对象类型将会在所有的指点向它的变量上有所反映。例2-1即此一例,两个变量指向同一个对象,但是对对象内容的修改的反映是全局的。程序2-1.多变量引用单个对象的示例[Copytoclipboard][-]CODE://设置obj为一个空对象varobj=newObject();//objRef现在引用了别的对象varobjRef=obj;//修改原始对象的属性PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn13obj.oneProperty=true;//我们可以发现该变化在两个变量中都可以看到//(因为他们引用了同一个对象)alert(obj.oneProperty===objRef.oneProperty);我从前提到过自更改的对象在JavaScript里非常少见的。让我们看一个发生这一状况的实例。数组对象能够用push方法给它自己增加额外的项。因为在数组对象的核心,值是作为对象的属性存储的,结果类似程序2-1中的情形,一个对象成为全局被改动的(导致了多个变量的值被同时改变)。见程序2-2.程序2-2.自修改对象的例子[Copytoclipboard][-]CODE://创建一组项目的数组varitems=newArray("one","two","three");//创建一个对项目数组的引用varitemsRef=items;//给原始数组添加一项items.push("four");//两个数组的长度应该相同,//因为它们都指向相同的数组对象alert(items.length==itemsRef.length);记住这一点是很重要的:引用总是只指向最终被引用的对象,而不会是引用本身。例如,在Perl语言里,很可能有一个引用指向另一个也是引用的变量。但在JavaScript里,它会沿着引用链向下追溯直到指向核心的对象。程序2-3演示了这种情形,物理的目标已经改变而引用仍然指向原来的对象。程序2-3.ChangingtheReferenceofanObjectWhileMaintainingIntegrity(见#9oerrite的回复)[Copytoclipboard][-]CODE://设置items为一个字符串的数组(对象)varitems=newArray("one","two","three");//设置itemsRef为对items的引用varitemsRef=items;//让items指向一个新的对象items=newArray("new","array");//items和itemsRef现在指向不同的对象//items指向newArray("new","array")//itemsRef则指向newArray("one","two","three")alert(items!==itemsRef);PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn14最后,让我们来看一个陌生的例子,表面似乎是一个自修改的对象,却作用于一个新的未被引用的对象。当执行字符串串联时,结果总是一个新的字符串对象,而非原字符串更改后的版本。这在程序2-4中可以看出。程序2-4.对象修改作用于一个新的对象而非自修改对象的示例[Copytoclipboard][-]CODE://让item等于一个新的字符串对象varitem="test";//itemRef也引用相同的字符串对象varitemRef=item;//在字符串对象上串联一个新的对象//注意:这创建了一个新的对象,并不修改初始对象item+="ing";//item和itemRef的值并不相等,因为//一个全新的对象被创建了alert(item!=itemRef);如果你刚刚接触,引用可能是个令人头大的刁钻话题。然而,理解引用是如何工作的对于编写良好、干净的JavaScript代码是极其重要的。接下来的几节我们将探究几种未必新鲜和令人激动的,但是同样对编写良好、干净的代码很重要的特性。函数重载和类型检查其它面向对象的语言(比如Java)的一种共有的特性是“重载”函数的能力:传给它们不同数目或类型的参数,函数将执行不同操作。虽然这种能力在JavaScript中不是直接可用的,一些工具的提供使得这种探求完全成为可能。在JavaScript的每一个函数里存在一个上下文相关的名为arguments的变量,它的行为类似于一个伪数组,包含了传给函数的所有参数。参数不是一真正的数组(意味着你不能修改它,或者调用push()方法增加新的项),但是你可以以数组的形式访问它,而且它也的确有一个length属性。程序2-5中有两个示例。程序2-5.JavaScript中函数重载的两个示例[Copytoclipboard][-]CODE://一个简单的用来发送消息的函数functionsendMessage(msg,obj){//如果同时提供了一个消息和一个对象if(arguments.length==2)//就将消息发给该对象obj.handleMsg(msg);PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn15//否则,刚假定只有消息被提供else//于是显示该消息alert(msg);}//调用函数,带一个参数–用警告框显示消息sendMessage("Hello,World!");//或者,我们也可以传入我们自己的对象用//一种不同方式来显示信息sendMessage("Howareyou?",{handleMsg:function(msg){alert("Thisisacustommessage:"+msg);}});//一个使用任意数目参数创建一个数组的函数functionmakeArray(){//临时数组vararr=[];//遍历提交的每一个参数for(vari=0;i<arguments.length;i++){arr.push(arguments[i]);}//返回结果数组returnarr;}另外,存在另一种断定传递给一个函数的参数数目的方法。这种特殊的方法多用了一点点技巧:我们利用了传递过来的任何参数值不可能为undefined这一事实。程序2-6展示一了个简单的函数用来显示一条错误消息,如果没有传给它,则提供一条缺省消息。程序2-6:显示错误消息和缺省消息[Copytoclipboard][-]CODE:functiondisplayError(msg){//检查确保msg不是undefinedif(typeofmsg=='undefined'){//如果是,则设置缺省消息msg="Anerroroccurred.";}//显示消息alert(msg);}PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn16typeof语句的使用引入了类型检查。因为JavaScript(目前)是一种动态类型语言,使得这个话题格外有用而重要的话题。有许多种方法检查变量的类型;我们将探究两种特别有用的。第一种检查对象类型的方式是使用显式的typeof操作符。这种有用的方法给我们一个字符串名称,代表变量内容的类型。这将是一种完美的方案,除非变量的类型或者数组或自定义的对象如user(这时它总返回"ojbect",导致各种对象难以区分)。这种方法的示例见程序2-7程序2-7.使用typeof决定对象类型的示例[Copytoclipboard][-]CODE://检查我们的数字是否其实是一个字符串if(typeofnum=="string")//如果是,则将它解析成数字num=parseInt(num);//检查我们的数组是否其实是一个字符串if(typeofarr=="string")//如果是,则用逗号分割该字符串,构造出一个数组arr=arr.split(",");检查对象类型的第二种方式是参考所有JavaScript对象所共有的一个称为constructor的属性。该属性是对一个最初用来构造此对象的函数的引用。该方法的示例见程序2-8。程序2-8.使用constructor属性决定对象类型的示例[Copytoclipboard][-]CODE://检查我们的数字是否其实是一个字符串if(num.constructor==String)//如果是,则将它解析成数字num=parseInt(num);//检查我们的字符串是否其实是一个数组if(str.constructor==Array)//如果是,则用逗号连接该数组,得到一个字符串str=str.join(',');表2-1显示了对不同类型对象分别使用我所介绍的两种方法进行类型检查的结果。表格的第一列显示了我们试图找到其类型的对象。每二列是运行typeofVariable(Variable为第一列所示的值)。此列中的所有结果都是字符串。最后,第三列显示了对第一列包含的对象运行Variable.constructor所得的结果。些列中的所有结果都是对象。表2-1.变量类型检查———————————————————————————————VariabletypeofVariableVariable.constructorPDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn17———————————————————————————————{an:"object"}objectObject["an","array"]objectArrayfunction(){}functionFunction"astring"stringString55numberNumbertruebooleanBooleannewUser()objectUser——————————————————————————————————使用表2-1的信息你现在可以创建一个通用的函数用来在函数内进行类型检查。可能到现在已经明显,使用一个变量的constructor作为对象类型的引用可能是最简单的类型检查方式。当你想要确定精确吻合的参数数目的类型传进了你的函数时,严格的类型检查在这种可能会大有帮助。在程序2-9中我们可以看到实际中的一例。程序2-9.一个可用来严格维护全部传入函数的参数的函数[Copytoclipboard][-]CODE://依据参数列表来严格地检查一个变量列表的类型functionstrict(types,args){//确保参数的数目和类型核匹配if(types.length!=args.length){//如果长度不匹配,则抛出异常throw"Invalidnumberofarguments.Expected"+types.length+",received"+args.length+"instead.";}//遍历每一个参数,检查基类型for(vari=0;i<args.length;i++){//如JavaScript某一项类型不匹配,则抛出异常if(args[i].constructor!=types[i]){throw"Invalidargumenttype.Expected"+types[i].name+",received"+args[i].constructor.name+"instead.";}}}//用来打印出用户列表的一个简单函数functionuserList(prefix,num,users){//确保prefix是一个字符串,num是一个数字,//且user是一个数组strict([String,Number,Array],arguments);//循环处理num个用户for(vari=0;i<num;i++){PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn18//显示一个用户的信息print(prefix+":"+users[i]);变量类型检查和参数长度校验本身是很简单的概念,但是可用来实现复杂的方法,给开发者和你的代码的使用者提供更好的体验。接下来,我们将探讨JavaScript中的作用域以及怎么更好的控制它。作用域作用域是JavaScript中一个较难处理的特性。所有面向对象的编程语言都有某种形式的作用域;这要看是什么上下文约束着作用域。在JavaScript里,作用域由函数约束,而不由块约束(如while,if,和for里的语句体)。最终可能使得一些代码的运行结果表面上显得怪异(如果你来自一种块作用域语言的话)。程序2-10的例子说明了“函数作用域代码”的含义。代码2-10.JavaScript中变量作用域是怎样工作的例子[Copytoclipboard][-]CODE://设置一个等于"test"的全局变量foovarfoo="test";//在if块中if(true){//设置foo为"newtest"//注意:这仍然是在全局作用域中varfoo="newtest";}//正如我们在此处可见,foo现在等于"newtest"alert(foo=="newtest");//创建一个修改变量foo的函数functiontest(){varfoo="oldtest";}//调用时,foo却驻留在是在函数的作用域里面test();//确认一下,foo的值仍然是"newtest"alert(foo=="newtest");在程序2-10中你会发现,变量位于在全局作用域。基于浏览器的JavaScript有趣的一面是,所有的全局变量实际上都是window对象的属性。尽管一些老版本的Opera浏览器或Safari浏览器不是这样,假定浏览器这样工作通常是一个很好的经验规则。程序2-11展示了一个这种例子。程序2-11.JavaScript的全局变量与window对象的例子PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn19[Copytoclipboard][-]CODE://全局变量,包含字符串"test"vartest="test";//你会发现,我们的全局变量和window的test属性是相同的alert(window.test==test);最后,让我们来看看当一个变量漏定义时会怎样。程序2-12里,变量foo在test()的作用域里被赋值。但是,程序2-12里实际并没有(用varfoo)定义变量的作用域。当变量foo没有明确定义时,它将成为全局变量,即使它只在函数的上下文使用。程序2-12.隐式全局变量声明的示例[Copytoclipboard][-]CODE://一个为变量foo赋值的函数functiontest(){foo="test";}//调用函数为foo赋值test();//我们发现foo现在是全局变量了alert(window.foo=="test");到目前应该很明显,尽管JavaScript的作用域不如块作用域语言的严格,它还是相当强大和有特色的。尤其是与下节中叙述的闭包的概念结合起来时,JavaScript语言的强大将展露无遗。闭包闭包意味着内层的函数可以引用存在于包绕它的函数的变量,即使外层的函数的执行已经终止。这一特殊的论题可能是非常强大又非常复杂的。我强烈推荐你们参考本节后面将提及的站点,因为它有一些关于闭包这一话题的精彩的信息。我们先来看程序2-13所示的闭包的两个简单例子。程序2-13.闭包改善的代码清晰性的两例[Copytoclipboard][-]CODE://得到id为"main"的元素varobj=document.getElementById("main");//改变它的边框样式obj.style.border="1pxsolidred";//初始化一个1秒钟以后被调用的回调函数PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn20setTimeout(function(){//此函数将隐藏该元

javascript面向对象编程.pdf

javascript面向对象编程.pdf

上传者: weidong1365381
1152次下载 0人收藏 暂无简介 简介 2011-09-14 举报

简介:javascript教程,都非常经典

1第一部分:现代JavaScript简介第一章现代JavaScript编程JavaScript的演化是渐进而稳固的。历经过去十年的进程,JavaScript在人们的认知里已经从一门简单的玩物式的语言逐渐发展成为一门倍受推崇的编程语言,被全世界的公司和开发者用来构造种种精彩的应用。现代JavaScript编程语言一如既往地可靠、健壮,强大得令人难以置信。在本书中我进行的许多论述,将揭示是什么使得现代JavaScript应用程序与从前有着那么明显的不同。本章中出现的许多概念远不能算新奇,然而成千上万聪明的程序员的认同促使它们的用途得以升华并最终形成今天的格局。既如此,我们这就来着眼现代JavaScript程序设计。面向对象的JavaScript从语言的视角来看,面向对象的程序设计和面向对象的JavaScript语言绝对不是什么摩登的东西;JavaScript最开始就是被设计成一种彻底的面向对象语言。然而,随着JavaScript在其使用和接受的过程中的“逐步发展”,其它语言(如Ruby,Python,和Perl等)的程序员留意到了它并开始将他们的编程模式引入了JavaScript。面向对象的JavaScript代码的外观和内部运作都有别于其它具有对象能力的语言。在第二章我将深入论述使它如此独特的方方面面,而在这里,先来看一点基础的东西以体会编写现代JavaScript代码的初步感觉。程序1-1中的两个对象构造器的例子,演示了可用于学校课程的简单的对象搭配。程序1-1.课程和课程表的面向对象JavaScript表述CODE://类Lecture的构造器//使用两个字符串参数,name和teacherfunctionLecture(name,teacher){//把它们作为对象的本地属性保存this.name=name;this.teacher=teacher;}//类Lecture的方法,生成一个显示该课程信息的字符串Lecture.prototype.display=function(){returnthis.teacher+"isteaching"+this.name;};//类Schedule的构造器//使用一个lectures类型的数组作为参数PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn2functionSchedule(lectures){this.lectures=lectures;}//类Schedule的方法,用来构造一个描述该课程表的字符串Schedule.prototype.display=function(){varstr="";//遍历每门课程,累加构成信息字符串for(vari=0;i<this.lectures.length;i++)str+=this.lectures[i].display()+"";returnstr;};从程序1-1的代码中你或许已经看出,大部分的面向对象基本原则贯穿存在于其中,但它们是以不同于其它更常见的面向对象语言的方式组织起来的。你可以创建对象构造器和方法,并存取对象属性。程序1-2展示了在应用程序中使用上面两个类的一个示例。程序1-2.给用户提供课程的列表CODE://创建一个新的课表对象,存于变量mySchedule中varmySchedule=newSchedule([//创建一个课程对象的数组,//作为传给课表(原文此处为Lecture,疑为笔误)对象的唯一参数newLecture("Gym","Mr.Smith"),newLecture("Math","Mrs.Jones"),newLecture("English","TBD")]);//弹出对话框显示课表的信息alert(mySchedule.display());伴随对广大程序员对JavaScript的接受,设计良好的面向对象代码的使用也正日益普及。贯穿本书的始末,我将试图展示我认为能够最好地例示代码设计与实现的不同的面向对象的JavaScript代码片段。测试你的代码建立起良好的面向对象的基本代码之后,开发专业品质的JavaScript代码的第二个方面是确保拥有一个强劲的代码测试环境。当开发频繁使用的或将由其它开发者维护的代码时,严格调试的必要性会显得尤为突出。为其它开发者提供一个坚实的测试基础,是维持代码开发活动的关键。在第四章,你将会看到一些可用来形成良好的测试/使用框架的不同工具,以及对复杂应用程序的简单调试。用于Firefox的插件Firebug就是其中一例。Firebug提供了许多的有PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn3用的工具,如错误控制台,HTTP请求日志,调试,以及元素查看。图1-1展示了Firebug调试一段代码时的实况截屏。图1-1.FirefoxFirebug插件运行时的截屏开发干净的、可测试的代码的重要性怎么强调都不会过分。一旦你开始开发一些干净的面向对象代码并将它们与合适的测试套件结合,相信你会倾向于同意这一点。为分发而进行的封装开发现代的专业JavaScript代码的最后一个方面是为了代码分发或在现实世界里中使用而进行的封装处理。随着开始开发者们在其页面中使用越来越多的JavaScript代码,冲突的可能性将会增加。如果两个JavaScript库里都有一个名为data的变量或者按各的意图添加事件,灾难性的冲突和莫名其妙的错误可能就会出现。开发者简单地置入<script>指针无须任何变动就能正常工作的能力是开发一个成功的JavaScript库的精诣所在。开发者用以保持代码清洁和普遍兼容的的技术或解决方案有许多种。使用命名空间是广泛使用的保证代码不与其它JavaScript代码互相影响和抵触的一种技术。这方面一个极端的(但未必是最好或最有用的)运作中的例子就是Yahoo开发的任何人都可使用的用户界面库。使用该库的一个示例见程序1-3.程序1-3.使用重度名称空间化的YahooUI库给一个元素添加事件CODE://给ID为"body"的元素添加mouseover事件监听器YAHOO.util.Event.addListener('body','mouseover',function(){//andchangethebackgroundcoloroftheelementtoredthis.style.backgroundColor='red';});然而,这种命名空间方法存在一个问题,即库与库之间在构造和使用的方式上缺乏内在PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn4的一致性。正是在这一点上,中心代码仓库如JSAN(JavaScriptArchiveNetwork)变得非常有用。JSAN提供一套代码库需遵从的一致规则,以及一种快捷导入代码所依赖的其它库的方式。图1-2展示了JSAN的主分发中心的一个截屏。图1-2.公共代码仓库JSAN的截屏我将在第三章阐述开发清洁的可封装代码的细节。此外,其它常见的事故多发点如事件处理冲突,将在第六章论述。UnobtrusiveDOM脚本编程(非侵入的DOM脚本编程)基于一个优良的可测试的核心创建你的代码和兼容的分发,是UnobtrusiveDOM脚本编程的基本概念。编写unobtrusive代码意味着与你的HTML内容的彻底分离:数据来自服务器,而JavaScript代码用来使其动态化。达到这一彻底分离的最重要的副作用就是你的代码在不同的浏览器之间可以完美的升/降级。利用这一点,你可以提供高级的内容给支持它的浏览器,而在不支持的浏览器上从容隐藏之。编写现代的、Unobtrusive代码包括两个方面:文档对象模型(DOM)和JavaScript事件。本书中我对这两个方面都将作深入的解释。PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn5文档对象模型DOM是表示XML文档的流行的方法。它未必是最快的、最轻便的、或者最易使用的,却是是最普及的,绝大多数web开发语言(如Java,Perl,PHP,Ruby,Python,及Javascript)都实现了对它的支持。DOM旨在为开发者提供一种直观的方式来导航于XML的层次结构中。因为有效的HTML只是XML的一个子集,保有一个方式来有效地解析和浏览DOM文档对于简化JavaScript开发来说是必不可少的。从根本上讲,出现在JavaScript中的大多数的交互是发生在JavaScript与页面所包含的不同HTML元素之间的;DOM是使这此过程简单化的卓越工具。程序1-4展示了使用DOM在页内导航和查找不同的元素然后操作它们的一些例子。程序1-4.使用文档对象模型定位并操纵不同的DOM元素[Copytoclipboard][-]CODE:<html><head><title>IntroductiontotheDOM</title><script>//直到文档完全载入,我们才能操作DOMwindow.onload=function(){//找到文档中所有的<li>元素varli=document.getElementsByTagName("li");//然后给它们全部加上边框for(varj=0;j<li.length;j++){li[j].style.border="1pxsolid#000";}//定位ID为'everywhere'的元素varevery=document.getElementById("everywhere");//并将它从文档中移除every.parentNode.removeChild(every);};</script></head><body><h1>IntroductiontotheDOM</h1><pclass="test">ThereareanumberofreasonswhytheDOMisawesome,herearesome:</p><ul><liid="everywhere">Itcanbefoundeverywhere.</li><liclass="test">It'seasytouse.</li><liclass="test">Itcanhelpyoutofindwhatyouwant,PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn6reallyquickly.</li></ul></body></html>DOM是开发UnobtrusiveJavaScript代码的第一步。借助简单快速导航HTML文档的能力,所有随之而来的JavaScript/HTML交互将变得如此简单。事件事件将一个应用程序之内所有的用户交互结合在一起。在一个设计良好的JavaScript应用程序里,你将拥有数据源和它的视觉的表示(在HTMLDOM内部)。为了同步这两个方面,你必须监视用户的交互动作并试图相应地更新用户界面。使用DOM和JavaScript事件的结合是使得现代web应用程序赖以工作的基本组合。所有的现代浏览器都提供一系列的只要特定交互动作发生即被触发的事件,如用户移动鼠标,敲击键盘,或离开页面等等。使用这些事件,你可以注册代码到特定事件,一旦该事件发生,你的代码就会被执行。程序1-5展示了这种交互的一个实例,该网页中的<li>元素在用户鼠标经过的时候会改变背景色。程序1-5.使用DOM和事件来提供一些视觉效果[Copytoclipboard][-]CODE:<html><head><title>IntroductiontotheDOM</title><script>//直到文档完全载入,我们才能操作DOMwindow.onload=function(){//查找所有的<li>元素,附以事件处理程序varli=document.getElementsByTagName("li");for(vari=0;i<li.length;i++){//将鼠标移入事件处理程序附在<li>元素上,//该程序改变<li>背景颜色为蓝色li[i].onmouseover=function(){this.style.backgroundColor='blue';};//将鼠标移出事件处理程序附在<li>元素上,//该程序将<li>的背景颜色改回白色li[i].onmouseout=function(){this.style.backgroundColor='white';};}PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn7};</script></head><body><h1>IntroductiontotheDOM</h1><pclass="test">ThereareanumberofreasonswhytheDOMisawesome,herearesome:</p><ul><liid="everywhere">Itcanbefoundeverywhere.</li><liclass="test">It'seasytouse.</li><liclass="test">Itcanhelpyoutofindwhatyouwant,reallyquickly.</li></ul></body></html>JavaScript事件是复杂多样的。本书中的大多数代码或应用程序都以某种方式利用了事件。第六章和附属B完全专注于事件及其交互。JavaScript与CSS动态HTML建立在DOM和事件交互的基础上。在核心层面上,动态HTML表示发生在JavaScript和附着在DOM元素上的CSS信息的交互。层叠式样式表(CSS)作为布局的标准服务于简单的不唐突的网页,在最小化了用户端兼容性问题的同时,提供给开发者以强大的可控制性。从根本上讲,动态HTML就是探索JavaScript和CSS彼此交互作用时能够达到什么以及怎样最好地利用该联合达成令人印象深刻的效果。更高级的交互示例如拖放元素和动画效果见第七章。在那里我将围绕它们展开深入论述。AjaxAjax,或曰异步Javascript与XML,是由AdaptivePath公司的创办人之一兼董事长JesseJamesGarrett在其论文"Ajax:Web应用程序的新途径"(http://www.adaptivepath.com/publ...archives/000385.php)中创造的一个术语。它描述了请求和提交额外的信息时发生于客户和服务器之间的高级交互。术语Ajax包括了许多种数据据通讯的可能组合,但它们都围绕一个中心前提:附加的数据请求是在页面完全载入之后由客户端向服务器发起的。这允许应用程序开发者超越缓慢的、传统的应用程序流程,创建与用户相关的额外交互。图1-3是来自Garrett的Ajax论文的一个图示,说明了应用程序中由于额外的请求发生在后台(而且用户很可能并不知情),交互的流程发生了怎样的改变。PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn8图1-3:来自文章"Ajax:Web应用程序的新途径"的图示,展示发生于客户和服务器之间的先进的异步的交互Garrett论文的最初发表,激起了用户、开发者、设计者以及管理者们的兴趣,使用高级交互的新型应用程序爆炸式地增长。讽刺的是,在这一兴趣复苏的同时,Ajax背后的技术却是相当陈旧的(在2000年左右就有已有了商业上的应用)。然而最主要的不同在于,老的应用程序利用了浏览器特有的方式与服务器通讯(如仅ie具有的功能)。由于所有的现代浏览器都支持XMLHttpRequest(发送或从服务器接收数据的主要手段),theplayingfieldhasbeenleveled(见#12cfs178的回复),每个人都可以享受其益处。如果说有一个公司走在了利用Ajax技术创建优秀应用程序的最前列,那无疑是Google。恰在最初的Ajax论文出现之前,它发布了一个高交互性的domo:GoogleSuggest。该demo可以实时地自动完成你所键入的查询,这是旧式的页面重载不可能达到的功能。图1-4是GoogleSuggest运行时的一个截屏。PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn9图1-4.GoogleSuggest,早于Garrett的Ajax论文的利用了异步XML技术的应用程序除此而外,Google的另一个革命性的应用程序为GoogleMap,用户在其地图上移动将会实时地看到相关的局部结果。这一程序通过使用Ajax技术而提供的速度和可用性的水平是其它任何可用的地图程序所无法比拟的,结果彻底地变革了在线地图市场。图1-5是GoogleMap的截屏.图1-5.GoogleMaps,利用了一些Ajax技术来动态载入特定区域信息PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn10浏览器支持JavaScript开发所面临的不幸事实是,因为与实现和支持它的浏览器关联过于紧密,它受到当前最流行浏览器的支配。由于用户未必会使用对JavaScript支持得最好的浏览器,我们被迫对哪些是最重要的功能作出抉择。许多开发者已经开始做的是去掉对那些导致过多开发障碍的浏览器的支持。因为它们用户群的规模和还是因为它们拥有你喜欢的功能而考虑对浏览器的支持,需要仔细的权衡。最近Yahoo发布了一个可用来扩展你的web应用程序的JavaScript库。连同那个库,它还发布了一些供web开发者遵从的指导方针。以我之见,从中产生的最重要的文档是Yahoo支持与不支持的各种浏览器的官方的列表。尽管任何人或任何公司都可以做类似的事情,一份由互联上访问最频繁的网站所提供的文档,其价值绝对无法估量。Yahoo开发了一个分级的浏览器支持策略,对浏览器指定特定的级别并依据其功能为它提供不同的内容。Yahoo给浏览器三个级别:A,X和C:A级浏览器是得到完全支持和测试的,Yahoo的所有程序都能有保障在其中运行。X级浏览器是Yahoo认可但是没能彻底测试的准A级浏览器,或者是崭新的从未遇到过的浏览器。X级浏览器被期望能处理高级的内容,与A级浏览器等同对待。C级浏览器是已知的“劣质的”浏览器,不支持运行Yahoo应用程序所必须的功能。由于Yahoo应用程序完全Unobtrusive(即使没有JavaScript它们也能继续工作),这些浏览器只需处理不含JavaScript的功能性的内容。顺便一提,Yahoo的浏览器级别选择竟与我的不谋而合,这使得它尤其富有吸引力。在这本书里,我大量地使用了术语“现代浏览器”,当我用这一措词的时候,我指的Yahoo浏览器分级表评定为A级的任浏览器。给定一组赖以工作的一致的功能,减少因避免浏览器的不兼容而带来的痛苦,学习和开发的经历将会变得更加有趣。我极力推荐你们去通读浏览器分级的支持文档(见http://developer.yahoo.com/yui/articles/gbs/gbs.html,该文档包含了图1-6所示的浏览器支持表),感受一下Yahoo力图实现的是什么。通过将些信息公之于web开发的大众,Yahoo正在给出一条无价的“黄金标准”让其它所有人去靠拢,这是很了不起的。PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn11图1-6.Yahoo提供的浏览器分组支持表更多的关于浏览器支持情况的信息请参看本书的附录C,那里对每种浏览器的缺点和长处都有深入的论讨。或多或少地,你会发现所有的A级浏览器都走在发展的最前列,提供了远远超出你的开发所需要的功能。当选择你希望支持哪些浏览器时,最终结果实际上可以归结为你的应用程序支持的一组功能。如果你想要支持NS4或IE5(举个例子来说),则势必严格地限制你可以在程序中使用的功能的数量,因为它们缺乏对现代编程技术的支持。尽管如此,了解哪些浏览器是现代的允许你利用其中可用的强大的功能并给你一个可供将来的开发所依据的稳固的基础。这一稳固的开发基础可由以下几种功能所定义:核心Javascript1.5:最近、最广泛接受的JavaScript版本。它全面支持面向对象的JavaScript。IE5.0不支持全部的1.5,这是开发者们不愿意支持它的主要原因。XML文档对象模型(DOM)2:用来访问HTML和XML文档的的标准方案。这绝对是编写高效率的程序不可或缺的。XMLHttpRequest:Ajax技术的支柱——用来发起HTTP请求的一个简单层。所有的浏览器默认都支持这一对象,除了IE5.0-6.0;而它们也都支持用ActiveX初始化功能相当的对象。CSS:网页设计的基本需求。这似乎像是一个额外的需求,但是拥有CSS对web应用程序开发者来说是必不可少的。由于每一种现代浏览器都支持CSS,大多数问题的发生通常归结为呈现方面的差异。这正是IEforMac较少被频繁支持的主要原因。以上这些浏览器功能的结合构成了开发JavaScriptweb应用程序的支柱。所有的现代浏览器都以某种方式支持以上列举的功能。本书论述的所有内容都基于这一假设:你所使用的浏览器最起码能支持它们本章摘要本书试图完全包括所有现代、专业的JavaScript编程技术,以期它们被从独立开发者到大型公司的每一个人使用,使得其代码更加可用、可读、具有交互性。PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn12在这一章里我们对这本书里将会出现的每一个知识点做了一个简短的总览。这包括专业JavaScript编程的基础:编写面象对代码,测试代码,为分发而进行封装。随后你看到了UnobtrusiveDOM脚本编程的主要方面,包括一个关于文档对象模型,事件,JavaScript与CSS交互的简短的总览。最后你看到了Ajax背后的前提和在现代浏览器中JavaScript的支持。这些话题加在一起,足够带你步入专业级JavaScript程序员的行列。第二部分专业的JavaScript开发第二章面对对象的JavaScript对象是JavaScript的基本单位。实际上JavaScript中一切都是对象并得益于这一事实。然而,为了增强这一纯粹的面向对象的语言,JavaScript包括了一个庞大的功能集,使它无论是在潜在能力还是风格上,都成为一门极其独特的语言。本章中我将开始覆盖JavaScript语言的最重要的一些方面,如引用,作用域,闭包,以及上下文,你会发现这正是其它JavaScript书籍中很少论及的。打下主要的基础以后,我们将开始探索面向对象JavaScript的几个重点,包括对象到底如何运作和怎样创建新的对象并在特定的许可条件下设置其方法。如果你认真去读的话,这很可能是本书中最重要的一章,它将彻底地改变你看待JavaScript作为一门编程语言的方式。语言特性引用JavaScript的一个重要的方面是引用的概念。引用就是指向对象实际位置的指针。这是一项极其强大的功能。前提是,实际的对象决不是一个引用:字符串总是一个字符串,数组总是一个数组。然而,多个变量可以引用相同的对象。JavaScript就是以这种引用引用机制为基础。通过维护一系列的指向其它对象的引用,语言为你提供了更大的弹性。另外,对象能包括一系列的属性,这些属性简单地引用其它对象(如字符串,数字,数组等等)。当几个变量指向相同对象时,修改底层对象类型将会在所有的指点向它的变量上有所反映。例2-1即此一例,两个变量指向同一个对象,但是对对象内容的修改的反映是全局的。程序2-1.多变量引用单个对象的示例[Copytoclipboard][-]CODE://设置obj为一个空对象varobj=newObject();//objRef现在引用了别的对象varobjRef=obj;//修改原始对象的属性PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn13obj.oneProperty=true;//我们可以发现该变化在两个变量中都可以看到//(因为他们引用了同一个对象)alert(obj.oneProperty===objRef.oneProperty);我从前提到过自更改的对象在JavaScript里非常少见的。让我们看一个发生这一状况的实例。数组对象能够用push方法给它自己增加额外的项。因为在数组对象的核心,值是作为对象的属性存储的,结果类似程序2-1中的情形,一个对象成为全局被改动的(导致了多个变量的值被同时改变)。见程序2-2.程序2-2.自修改对象的例子[Copytoclipboard][-]CODE://创建一组项目的数组varitems=newArray("one","two","three");//创建一个对项目数组的引用varitemsRef=items;//给原始数组添加一项items.push("four");//两个数组的长度应该相同,//因为它们都指向相同的数组对象alert(items.length==itemsRef.length);记住这一点是很重要的:引用总是只指向最终被引用的对象,而不会是引用本身。例如,在Perl语言里,很可能有一个引用指向另一个也是引用的变量。但在JavaScript里,它会沿着引用链向下追溯直到指向核心的对象。程序2-3演示了这种情形,物理的目标已经改变而引用仍然指向原来的对象。程序2-3.ChangingtheReferenceofanObjectWhileMaintainingIntegrity(见#9oerrite的回复)[Copytoclipboard][-]CODE://设置items为一个字符串的数组(对象)varitems=newArray("one","two","three");//设置itemsRef为对items的引用varitemsRef=items;//让items指向一个新的对象items=newArray("new","array");//items和itemsRef现在指向不同的对象//items指向newArray("new","array")//itemsRef则指向newArray("one","two","three")alert(items!==itemsRef);PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn14最后,让我们来看一个陌生的例子,表面似乎是一个自修改的对象,却作用于一个新的未被引用的对象。当执行字符串串联时,结果总是一个新的字符串对象,而非原字符串更改后的版本。这在程序2-4中可以看出。程序2-4.对象修改作用于一个新的对象而非自修改对象的示例[Copytoclipboard][-]CODE://让item等于一个新的字符串对象varitem="test";//itemRef也引用相同的字符串对象varitemRef=item;//在字符串对象上串联一个新的对象//注意:这创建了一个新的对象,并不修改初始对象item+="ing";//item和itemRef的值并不相等,因为//一个全新的对象被创建了alert(item!=itemRef);如果你刚刚接触,引用可能是个令人头大的刁钻话题。然而,理解引用是如何工作的对于编写良好、干净的JavaScript代码是极其重要的。接下来的几节我们将探究几种未必新鲜和令人激动的,但是同样对编写良好、干净的代码很重要的特性。函数重载和类型检查其它面向对象的语言(比如Java)的一种共有的特性是“重载”函数的能力:传给它们不同数目或类型的参数,函数将执行不同操作。虽然这种能力在JavaScript中不是直接可用的,一些工具的提供使得这种探求完全成为可能。在JavaScript的每一个函数里存在一个上下文相关的名为arguments的变量,它的行为类似于一个伪数组,包含了传给函数的所有参数。参数不是一真正的数组(意味着你不能修改它,或者调用push()方法增加新的项),但是你可以以数组的形式访问它,而且它也的确有一个length属性。程序2-5中有两个示例。程序2-5.JavaScript中函数重载的两个示例[Copytoclipboard][-]CODE://一个简单的用来发送消息的函数functionsendMessage(msg,obj){//如果同时提供了一个消息和一个对象if(arguments.length==2)//就将消息发给该对象obj.handleMsg(msg);PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn15//否则,刚假定只有消息被提供else//于是显示该消息alert(msg);}//调用函数,带一个参数–用警告框显示消息sendMessage("Hello,World!");//或者,我们也可以传入我们自己的对象用//一种不同方式来显示信息sendMessage("Howareyou?",{handleMsg:function(msg){alert("Thisisacustommessage:"+msg);}});//一个使用任意数目参数创建一个数组的函数functionmakeArray(){//临时数组vararr=[];//遍历提交的每一个参数for(vari=0;i<arguments.length;i++){arr.push(arguments[i]);}//返回结果数组returnarr;}另外,存在另一种断定传递给一个函数的参数数目的方法。这种特殊的方法多用了一点点技巧:我们利用了传递过来的任何参数值不可能为undefined这一事实。程序2-6展示一了个简单的函数用来显示一条错误消息,如果没有传给它,则提供一条缺省消息。程序2-6:显示错误消息和缺省消息[Copytoclipboard][-]CODE:functiondisplayError(msg){//检查确保msg不是undefinedif(typeofmsg=='undefined'){//如果是,则设置缺省消息msg="Anerroroccurred.";}//显示消息alert(msg);}PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn16typeof语句的使用引入了类型检查。因为JavaScript(目前)是一种动态类型语言,使得这个话题格外有用而重要的话题。有许多种方法检查变量的类型;我们将探究两种特别有用的。第一种检查对象类型的方式是使用显式的typeof操作符。这种有用的方法给我们一个字符串名称,代表变量内容的类型。这将是一种完美的方案,除非变量的类型或者数组或自定义的对象如user(这时它总返回"ojbect",导致各种对象难以区分)。这种方法的示例见程序2-7程序2-7.使用typeof决定对象类型的示例[Copytoclipboard][-]CODE://检查我们的数字是否其实是一个字符串if(typeofnum=="string")//如果是,则将它解析成数字num=parseInt(num);//检查我们的数组是否其实是一个字符串if(typeofarr=="string")//如果是,则用逗号分割该字符串,构造出一个数组arr=arr.split(",");检查对象类型的第二种方式是参考所有JavaScript对象所共有的一个称为constructor的属性。该属性是对一个最初用来构造此对象的函数的引用。该方法的示例见程序2-8。程序2-8.使用constructor属性决定对象类型的示例[Copytoclipboard][-]CODE://检查我们的数字是否其实是一个字符串if(num.constructor==String)//如果是,则将它解析成数字num=parseInt(num);//检查我们的字符串是否其实是一个数组if(str.constructor==Array)//如果是,则用逗号连接该数组,得到一个字符串str=str.join(',');表2-1显示了对不同类型对象分别使用我所介绍的两种方法进行类型检查的结果。表格的第一列显示了我们试图找到其类型的对象。每二列是运行typeofVariable(Variable为第一列所示的值)。此列中的所有结果都是字符串。最后,第三列显示了对第一列包含的对象运行Variable.constructor所得的结果。些列中的所有结果都是对象。表2-1.变量类型检查———————————————————————————————VariabletypeofVariableVariable.constructorPDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn17———————————————————————————————{an:"object"}objectObject["an","array"]objectArrayfunction(){}functionFunction"astring"stringString55numberNumbertruebooleanBooleannewUser()objectUser——————————————————————————————————使用表2-1的信息你现在可以创建一个通用的函数用来在函数内进行类型检查。可能到现在已经明显,使用一个变量的constructor作为对象类型的引用可能是最简单的类型检查方式。当你想要确定精确吻合的参数数目的类型传进了你的函数时,严格的类型检查在这种可能会大有帮助。在程序2-9中我们可以看到实际中的一例。程序2-9.一个可用来严格维护全部传入函数的参数的函数[Copytoclipboard][-]CODE://依据参数列表来严格地检查一个变量列表的类型functionstrict(types,args){//确保参数的数目和类型核匹配if(types.length!=args.length){//如果长度不匹配,则抛出异常throw"Invalidnumberofarguments.Expected"+types.length+",received"+args.length+"instead.";}//遍历每一个参数,检查基类型for(vari=0;i<args.length;i++){//如JavaScript某一项类型不匹配,则抛出异常if(args[i].constructor!=types[i]){throw"Invalidargumenttype.Expected"+types[i].name+",received"+args[i].constructor.name+"instead.";}}}//用来打印出用户列表的一个简单函数functionuserList(prefix,num,users){//确保prefix是一个字符串,num是一个数字,//且user是一个数组strict([String,Number,Array],arguments);//循环处理num个用户for(vari=0;i<num;i++){PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn18//显示一个用户的信息print(prefix+":"+users[i]);变量类型检查和参数长度校验本身是很简单的概念,但是可用来实现复杂的方法,给开发者和你的代码的使用者提供更好的体验。接下来,我们将探讨JavaScript中的作用域以及怎么更好的控制它。作用域作用域是JavaScript中一个较难处理的特性。所有面向对象的编程语言都有某种形式的作用域;这要看是什么上下文约束着作用域。在JavaScript里,作用域由函数约束,而不由块约束(如while,if,和for里的语句体)。最终可能使得一些代码的运行结果表面上显得怪异(如果你来自一种块作用域语言的话)。程序2-10的例子说明了“函数作用域代码”的含义。代码2-10.JavaScript中变量作用域是怎样工作的例子[Copytoclipboard][-]CODE://设置一个等于"test"的全局变量foovarfoo="test";//在if块中if(true){//设置foo为"newtest"//注意:这仍然是在全局作用域中varfoo="newtest";}//正如我们在此处可见,foo现在等于"newtest"alert(foo=="newtest");//创建一个修改变量foo的函数functiontest(){varfoo="oldtest";}//调用时,foo却驻留在是在函数的作用域里面test();//确认一下,foo的值仍然是"newtest"alert(foo=="newtest");在程序2-10中你会发现,变量位于在全局作用域。基于浏览器的JavaScript有趣的一面是,所有的全局变量实际上都是window对象的属性。尽管一些老版本的Opera浏览器或Safari浏览器不是这样,假定浏览器这样工作通常是一个很好的经验规则。程序2-11展示了一个这种例子。程序2-11.JavaScript的全局变量与window对象的例子PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn19[Copytoclipboard][-]CODE://全局变量,包含字符串"test"vartest="test";//你会发现,我们的全局变量和window的test属性是相同的alert(window.test==test);最后,让我们来看看当一个变量漏定义时会怎样。程序2-12里,变量foo在test()的作用域里被赋值。但是,程序2-12里实际并没有(用varfoo)定义变量的作用域。当变量foo没有明确定义时,它将成为全局变量,即使它只在函数的上下文使用。程序2-12.隐式全局变量声明的示例[Copytoclipboard][-]CODE://一个为变量foo赋值的函数functiontest(){foo="test";}//调用函数为foo赋值test();//我们发现foo现在是全局变量了alert(window.foo=="test");到目前应该很明显,尽管JavaScript的作用域不如块作用域语言的严格,它还是相当强大和有特色的。尤其是与下节中叙述的闭包的概念结合起来时,JavaScript语言的强大将展露无遗。闭包闭包意味着内层的函数可以引用存在于包绕它的函数的变量,即使外层的函数的执行已经终止。这一特殊的论题可能是非常强大又非常复杂的。我强烈推荐你们参考本节后面将提及的站点,因为它有一些关于闭包这一话题的精彩的信息。我们先来看程序2-13所示的闭包的两个简单例子。程序2-13.闭包改善的代码清晰性的两例[Copytoclipboard][-]CODE://得到id为"main"的元素varobj=document.getElementById("main");//改变它的边框样式obj.style.border="1pxsolidred";//初始化一个1秒钟以后被调用的回调函数PDF文件使用"pdfFactoryPro"试用版本创建www.fineprint.cn20setTimeout(function(){//此函数将隐藏该元
  • 相关资料
  • 该用户的其他资料
  • 名称/格式
  • 下载次数
  • 资料大小
  • 名称/格式
  • 下载次数
  • 资料大小

用户评论

0/200
暂无评论
上传我的资料

资料阅读排行

关闭

请选择举报的类型

关闭

提示

提交成功!

感谢您对爱问共享资料的支持,我们将尽快核实并处理您的举报信息。

关闭

提示

提交失败!

您的举报信息提交失败,请重试!

关闭

提示

重复举报!

亲爱的用户!感觉您对爱问共享资料的支持,请勿重复举报噢!

全屏 缩小 放大
收藏
资料评价:

/ 150
所需积分:1 立即下载
返回
顶部
举报
资料
关闭

温馨提示

感谢您对爱问共享资料的支持,精彩活动将尽快为您呈现,敬请期待!