




已阅读5页,还剩142页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
JavaScript精粹用javascript判断窗口关闭事件functionwindow.onbeforeunload()if(event.clientXdocument.body.clientWidth&event.clientY0|event.altKey|event.ctrlKey)/判断event.altKey是为了Alt+F4关闭的情况;判断event.ctrlKey是为了Ctrl+W关闭的情况/document.body.clientWidth不包括滚动条,而关闭按钮恰好在滚动条右侧。window.event.returnValue=;1.浏览器不是软件的窗口,要该事件非常困难,因为关闭与刷新这两个事件就很难区分。2.都没有对应的事件,只能根据一些条件来判断,但未必准确。3.前进、后退、刷新、关闭都响应事件window.onbeforeunload。4.javascript之所以能得到某些事件属性和调用方法,是因为浏览器对象为他提供了接口,用COM的术语来说,是IDispatch接口,如果浏览器对象没有为他提供接口,他什么也干不了。所以有些功能在其它语言中可以实现,而在javascript中是永远无法实现的。 用onUnload方法在body标签里加入onUnload事件bodyonUnload=myClose()然后在javascript里定义myClose()方法,但是onUnload方法是在关闭窗口之后执行,不是在关闭窗口之前执行,如果你想在关闭窗口之前做判断,请用第一种方法本书将主要介绍JavaScript的实际应用,因为JavaScript的确是一种令人惊奇的编程语言,有很多独特的优势。只要花一点时间学习和思考,就可以使用JavaScript为网站带来更多的功能、更新颖的设计和更好的易用性。下面先介绍JavaScript的概念,然后讨论它的由来以及使用方法。1.1 JavaScript的定义JavaScript是一种用于增强Web网页与应用程序的交互能力和动态能力的脚本语言。JavaScript可以和Web网页的各种部件进行交互,例如HTML、CSS,并且可以使它们实时地变化,以响应用户的操作。毫无疑问,您一定看过网页中的JavaScript代码,大多是嵌入HTML元素中的,例如:也可能是作为一个script元素,链接到其他文件中:还可能直接在文件中编码:function saySomething(message) alert(message); saySomething(Hello world!);现在您还不用关心这些片段之间的区别。有很多方法可以用于将JavaScript代码插入网页中,后面的章节将会讨论具体细节。JavaScript由Netscape公司开发并在Netscape 2中实现,一开始它叫做LiveScript。不过另外一种流行的语言Java启发了Netscape公司将其更名为JavaScript,JavaScript拥有沟通浏览器和Java Applet的能力,Netscape公司也试图利用这一点大发利市。不过这个语言不是由Netscape公司独自开发的,虽然最初的开发由Netscape公司发起,但还有一家公司后来也参与其中,这就是微软公司。微软公司开发出了相似但又有一些不同的JScript,很明显,对于Web脚本这样一种重要的应用,微软公司不希望落后于任何竞争对手。1996年,有关JavaScript的研发成果被提交为国际标准,并被称为ECMA,所以JavaScript就成了ECMAScript或者ECMA-262。大多数人还是喜欢JavaScript这个名字。另外,有一点容易引起混淆,即除了名字和语法有一些相似以外,Java和JavaScript再没有什么相似之处了。1.2 JavaScript的限制JavaScript通常被作为一种客户端语言使用,这里所说的客户端,一般是指终端用户的Web浏览器。在浏览器中,JavaScript代码被解释并被执行,这点和服务端语言截然不同。所谓的服务端语言需要运行在服务器,并发送一些静态数据给客户端,例如PHP、ASP等。由于JavaScript根本无法和服务器的环境打交道,很多任务是通过PHP实现的,例如读写数据库,或者创建一个文本文件等。不过因为JavaScript可以与客户端环境交互,所以它能够根据客户端信息来做一些判断或操作,例如鼠标位置、元素的尺寸等,而这是服务端语言无法做到的。什么是ActiveX?如果您对微软的JScript已经很熟悉了,那么可能会想到“JavaScript也许可以通过ActiveX做些什么事”。没错,确实可以,不过ActiveX并不是ECMAScript的一个组成部分。ActiveX只是Windows操作系统的一种特别机制,以便Internet Explorer可以访问COM对象,而且通常ActiveX是运行于受信任的环境中的,例如Intranet。我们会很快遇到几个例外:IE中没有专门的安全设置的ActiveX控件(例如Flash插件,还有XMLHttpRequest)。但绝大多数情况下,对ActiveX的讨论不在本书范畴之内。通常,在任何一台计算机上运行的客户端的能力总是没有服务器端强大,所以,JavaScript并不适合用来进行大量数据的处理。但是它对少量数据的即时处理的能力对于客户端而言却有着莫大的吸引力,例如接受响应、验证表单等,这使得它成为一个完成此类任务的最佳选择。但是,试图评价服务器端语言和客户端语言的优劣却是不必要的。这两种语言不具有可比性,它们只是针对不同任务的工具而已,两者的交集也并不多。然而,对于客户端脚本和服务器脚本的交互能力的需求却导致新一代的Web脚本语言的产生,这种新脚本语言使用XmlHttpRequest来请求服务器数据,运行服务器端的脚本,同时在客户端处理结果。第18章将深入探讨这种技术。安全性限制正因为JavaScript可用于操作那些非常敏感的数据和程序,所以它的能力被严格地限制,以防止被人恶意使用。因此,JavaScript被禁止去做很多的事情。例如,它不能读取计算机的系统设置,或者操作硬件,也不能启动别的程序。一些本来在JavaScript中被禁止的特殊的交互在特定的页面元素中也可以被允许。例如,修改的值通常是没什么问题的,除非是一个文件上传区(例如,),往里面写入是被禁止的,因为这可以阻止恶意代码偷偷地让用户上传他本来不希望上传的文件。还有很多类似的限制,本书将通过大量的例子和应用一一展示。但这里还是可以简单地总结一下,下面是一个列表,列出了JavaScript中由于安全问题而被禁止的操作:l 不能打开和读取一个文件(除非在一个特别的环境之下,相关内容会在第18章讨论);l 不能在用户的计算机上创建和编辑文件(除了cookie,相关内容在第8章讨论);l 不能读取HTTP post数据;l 不能读取系统设置,或者用户计算机上的任何其他数据,除非是语言本身提供的数据或者是环境提供的宿主对象(host object)1;l 不能修改文本输入区域的值;l 不能修改一个从其他域载入的document的显示方式;l 不能关闭和修改工具栏或者其他任何没有向脚本开放的窗口元素。结果,JavaScript好像被禁止了太多的功能。另外,还有一点值得注意。很多浏览器提供了更加精细的权限控制,而不仅仅是一个允许或禁止的选项。例如,Opera可以禁止脚本关闭窗口,禁止移动窗口,禁止状态栏写入,禁止接收鼠标右键消息这个列表还可以列得更长。加上了这些限制,您能做的事情就更少了,不过通常不需要关心那些选项,在大多数情况下,那些选项是为了对付一些烦人的代码(走马灯式的滚动状态栏、禁止右键的脚本等)而准备的,所以如果不想写那些让人讨厌的脚本,这些限制完全不用放在心上。1.3 JavaScript的最佳实践JavaScript实践遇到的一个最大的问题首先是,如果用户的浏览器根本就不支持JavaScript怎么办?如果他关掉了浏览器对JavaScript的支持呢?再或者因为某些原因,他使用了别的不支持JavaScript的技术怎么办? 这个问题一言难尽,第16章将详细讨论解决方法。下面提出3个写好JavaScript代码的原则:l 逐步改进 为那些没有安装JavaScript的用户着想;l 谨慎地编码 内容和行为的隔离;l 一致的编码方式 使用括号和分号结束符。第一条原则可以在构建网站的时候提醒开发者,面临的用户多种多样。第二条原则使得维护代码的代价更小,同时,遇到不支持JavaScript的浏览器也可以提供无脚本的访问方式1。第三条原则则有助于编写出更易读、更清晰的代码。1.4 为那些没有JavaScript的用户着想(逐步改进)由于以下原因,用户可能会得不到JavaScript:l 他们用的设备根本就不支持脚本,或者仅以某种受限制的方式支持;l 他们位于代理服务器或者防火墙之后,JavaScript代码被过滤;l 他们故意禁用了JavaScript。第一种原因的用户很多,而且这些用户还在逐渐增长,包括一些小屏幕设备,如PDA;中等大小屏幕设备,如WebTV和Sony的PSP;还有一些老的部分支持JavaScript的浏览器,如Opera 5和Netscape 4。也许上面列出的那些用户占用户总数的比例不算很高,但那不重要。不管怎样,一些用户没有JavaScript,但还是需要向他们提供服务。没有什么好的办法来统计这样的用户究竟有多少,因为从服务器端检测客户端对JavaScript的支持是非常不可靠的,不过我曾经看过一个数据,关闭支持JavaScript功能的用户的比例大约是5%20%之间,当然,前提是我们把各种搜索引擎的爬虫机器人程序也算成了用户。方 法一种解决方案就是使用HTML的noscript元素。那么页面内容就可以被所有不支持脚本的浏览器以及被关闭了JavaScript支持的浏览器正确查看。虽然这也是一个可行的办法,不过在实际操作中不是太有用。因为noscript无法区分浏览器对脚本的支持程度。那些只是部分支持或者受限制地支持JavaScript的浏览器会试图执行比较复杂的脚本,因为它们甚至可能根本就不认识noscript标签,其结果是在这些浏览器中代码会不正常地终止,然后什么也没干。一个更好的办法是使用静态HTML,然后通过脚本对静态内容进行修改或者增加动态行为。下面看一个简单例子。这个代码片段是用一个未排序的列表作为主菜单结构,产生一个DHTML菜单。第15章将详细讨论有关内容,不过这个简单的例子在这里可以充分展示我们的方法: Home About Contact链接的列表是纯HTML,所以对于所有的用户来说,不管使用什么浏览器,都可以正常显示。如果脚本是被支持的,那么menu.js脚本就可以执行动态的操作,不过脚本不被支持时,内容仍然会显示。我们没有用什么明确的方法来区分不同浏览器对于JavaScript的支持程度,而只是提供了动态的内容,如果浏览器能够处理,它就会去处理,如果不能,那么只显示静态内容就行了。讨 论传统的方法是,用纯JavaScript代码生成独立的动态菜单,然后用noscript元素提供一个备用的静态的内容: Home About Contact 不过,正如前面所说的,网上的很多浏览器会在这样的代码前面失效,因为对JavaScript的支持往往不是一个简单的“是或不是”的问题。而这个方法提供了给所有浏览器的默认内容,又提供了一个可能有效的脚本功能。这种脚本方法就是所谓的逐步改进,对这种方法的使用将贯穿本书。不要提示太多!不管是这种方法还是noscript元素,都不应该被用来产生这样的消息给用户,“请打开JavaScript选项再继续。”对于某些用户,这种消息有点蛮横(“我干嘛要听您的?”);对于另外一些用户,这种消息可能是无用的(“我压根无法打开!”)或者根本是无意义的(“JavaScript是啥?”)。就像很多启动页面总是说,“请升级您的浏览器”这种消息对于大多数Web用户而言,就像在路上看到一个牌子,提示“请换一辆车。”有时候,开发者可能会碰到除JavaScript之外再无更好的办法来实现功能的情况。这时,我认为用一些静态信息来提示用户网页遇到兼容性问题是合理的(当然,这些和技术无关)。不过,在大多数情况下,应尽量避免显示这种信息,除非它的确有意义而且是必须要告知用户的。1.5 内容和行为的隔离(谨慎地编码)将内容从行为中分离,意味着按照网页的结构分离出不同的层次来。Jeffrey Zeldman曾经将Web开发形容为“三条腿的板凳”1,分别是内容(HTML)、表示(CSS)、行为(JavaScript),他不仅指出三者在功能上的不同,同时也表明他认为这三者应该被互相隔离开来。好的隔离方式将使得网站更容易维护,也更容易被理解和使用,同时对于老的或者支持特性较少的浏览器也能够提供相应的访问方式。方 法以下是一种极端情况,正好与理想的行为内容互相分离的方法南辕北辙,也可以直接在事件处理属性中直接写入内嵌的代码。但这会把页面搞得一团糟,应该极力避免:可以把完成这些工作的代码写成一个函数:定义一个函数来做这件事可以将大量的代码集中到一个单独的JavaScript文件中:File:separate-content-behaviors.js (excerpt)function changeBorder(element, to) element.style.borderColor = to;不过更好的方法是完全不使用内嵌的事件处理,而使用文档对象模型(DOM)来将事件处理绑定到HTML文档的元素中。DOM是一种标准的编程接口,它使得像JavaScript这样的语言可以直接访问HTML文档的内容,这也消除了出现在HTML文档中的JavaScript代码。HTML代码如下:JavaScript代码如下:File: separate-content-behaviors.jsfunction changeBorder(element, to) element.style.borderColor = to;var contentDiv = document.getElementById(content);contentDiv.onmouseover = function() changeBorder(red);contentDiv.onmouseout = function() changeBorder(black);这种方法允许增加、删除或者修改事件处理,而无需编辑HTML,而且,因为文档本身完全不依赖于这些脚本,所以那些不支持JavaScript的浏览器将丝毫不受影响。这种方法同时也增加了复用性,如果需要,也可以将相同的函数绑定到其他元素上,同样也不需要编辑HTML。这种方法让我们拥有了通过DOM访问元素的能力,第5章将深入探讨DOM。隔离的优点通过将内容和行为分隔开来,不仅使代码具有更广泛的适用性,同时这种分而治之的思考方式也将带来好处。因为HTML和JavaScript完全分离,当我们检视HTML代码的时候,不会忘记这个页面需要显示的核心内容,而这些内容应当不依赖于任何脚本。Andy Clark把这种方式叫做Web标准甜点1,这是一种有趣的类比,这种比喻方式认为一个好的Web网站设计应该是这样:当看过去时,应该看到组成整个甜点的隔离的优点不同层次。这种方式的反面是水果蛋糕,您无法看到蛋糕的不同组成部分。您所能看到的就是搞不清什么材料的一块整个的蛋糕。讨 论当把事件处理和如下的元素绑定起来的时候,需要注意,只有在那个元素实际存在的时候才能那么做。如果把处理脚本放到页面的head区,浏览器会报告发生错误,然后拒绝执行代码,因为content div在这个位置还没有被浏览器解读显示,而JavaScript却已经先被处理了。最直接的方法是把代码放到load事件处理中。这种方式最保险,因为load事件只有在整个页面已经完全载入的时候才会被激发:window.onload = function() var contentDiv = document.getElementById(content); ;或者更清楚一点,多写一点代码:window.onload = init;function init() var contentDiv = document.getElementById(content); 不过使用load事件的问题是,在整个页面中只能使用一次;如果有两个或者更多的脚本需要通过load事件来执行,那么每个脚本都会改写对load事件的处理。解决方法是对load事件采用更好的响应方式,1.8节将继续探讨这个问题。1.6 使用括号和分号结束符(一致的编码方式)在很多JavaScript的操作中,括号和分号是可选的,那么,既然是可有可无的,它们的价值何在?方 法虽然括号和分号通常是可选的而非必需的,但还是应当尽量多使用这两个符号,这样可以使其他人更容易阅读代码,甚至也能有助于自己以后阅读代码,而且通过复用和重新组织代码,可以避免很多问题。举个例子,如下的代码确实能够正常地工作:File: semicolons-braces.js (excerpt)if (something) alert(something)else alert(nothing)不过,这样的代码能够正常工作应该归功于JavaScript解释器自动插入分号的能力。每当解释器发现被截断的位于不同行的两段相邻代码,而且这些代码段单列在一行上会毫无意义,解释器就会在段之间插入分号。通过类似的机制,用于if-else语句的括号即使不存在也能够根据语法被推断出来,实际上是解释器做了查遗补漏的工作。虽然这些符号不是必需的,但是如果坚持使用它们,就会发现这些符号既容易记忆也容易使用,而且写出的代码更容易阅读。下面是一个稍微好一点的例子:File: semicolons-braces.js (excerpt)if (something) alert(something); else alert(nothing); 不过下面这个例子具有最佳的可读性:File: semicolons-braces.js (excerpt)if (something) alert(something);else alert(nothing);使用函数显式声明如果对JavaScript的复杂部分已经有了一些经验,那么可能会经常通过函数显式声明来创建匿名函数,并且将匿名函数赋值给JavaScript的变量或者对象的属性。在下面的代码中,定义的函数后面需要跟一个分号,因为其实它算是一个赋值语句。var saySomething = function(message) ;1.7 给页面添加脚本要想让脚本工作,首先需要在页面中将其载入。有两种技术可以做到这一点,而其中一种技术明显优于另一种。方 法第一种,也是最直接的方法,是把代码写入script元素中,正像前面看见过的那样:function saySomething(message) alert(message);saySomething(Hello world!);这种方法的问题在于,对于老的或者不支持script元素的浏览器,这些内容会被解释为文本。一种更好的替代方式是将脚本放入外部的一个JavaScript文件,如下:这条语句会载入一个外部的名叫what-is-javascript.js的JavaScript文件。这个文件中将包含前一个例子放入script元素中的代码,如下:File: what-is-javascript.jsfunction saySomething(message) alert(message);saySomething(Hello world!);采用这种方法,不支持script元素的浏览器会忽略JavaScript部分,也不会显示多余内容(因为该元素的内容实际上是空的),不过那些能够解读script的浏览器会载入并处理该脚本。这有助于脚本和内容的分离,而且很容易维护,可以在不同的页面中使用同一个脚本,而无须复制脚本,也无需维护多个拷贝。讨 论也许您对避免在页面中写入脚本这个建议有异议,“不会有问题的呀”,您可能还会说,“我可以使用HTML注释把代码框起来”。不过我认为那不是一个好主意,使用HTML注释来“隐藏”代码是一种非常坏的习惯,一定要记住这一点。1.7.1 用HTML注释框住代码解析器本来无需读取注释内容,更不用去执行它。不过现实情况是,被注释的JavaScript完全可以工作,这是一个历史遗留问题,也是一种妥协,不应该假定解析器会正确地略过注释,忽略注释中的JavaScript,实际上,应该假定解析器一定不能正确地读取注释。书中的所有例子都通过HTML提供(与之相对的是XHTML),所以这种假设是合理的。不过如果使用XHTML(使用application/xhtml+xml的MIME类型),在浏览器处理该文件之前,XML解析器能够正确地忽略其中的注释,这样,注释的JavaScript代码确实不会执行。不过,考虑到兼容性(以及良好的编程习惯),强烈建议您尽量不在注释中放入代码。JavaScript代码应该总是放到一个外部的JavaScript文件中。1.7.2 语言属性语言属性不再是必需的了。当Netscape 4和它同时代的浏览器成为了主流时,标签扮演了一个探测脚本支持的角色(在JavaScript 1.3中指定),并且影响着脚本解释器的工作方式。当JavaScript变成了ECMAScript时,指定JavaScript的版本已经毫无意义,语言属性已经被类型属性取代。这种属性指定了被包含文件的MIME类型,例如脚本和样式表的类型,而且这也是惟一的一种需要指定的类型: 实际上,值应该被指定为text/ecmascript,不过Internet Explorer不认识这种信息。我个人希望它最好能支持,因为我输入javascript几个字比较费劲,有好多次,在输入text/javascript的时候我都输错。1.8 让不同的脚本在同一页面中协同工作如果几个脚本总是不能协同工作,那么很有可能是因为这些脚本试图对某给定元素的同一种事件处理赋予了不同的处理函数。因为每个元素对每个事件只有一个处理方法,所以同一个事件的处理会被不同的处理函数重复地替换。方 法通常应该怀疑的是window对象的load事件处理,因为在同一页面中,只有一个脚本能够使用这个事件;如果两个或者多个脚本尝试使用该事件,那么最后一个脚本会将前面脚本的处理函数覆盖掉。可以在load事件处理函数中调用多个函数,如下:window.onload = function() firstFunction(); secondFunction();不过,如果这样做,就必须受限于在load事件的处理函数中完成所有的任务。另一个好一点的解决方案是提供一个函数,可以增加对load事件的处理而不与其他已经添加的处理函数冲突。使用下面的函数,可以添加任意数量的load事件的处理函数,而无需担心它们发生冲突:File: add-load-listener.jsfunction addLoadListener(fn) if (typeof window.addEventListener != undefined) window.addEventListener(load, fn, false); else if (typeof document.addEventListener != undefined) document.addEventListener(load, fn, false);else if (typeof window.attachEvent != undefined) window.attachEvent(onload, fn);else var oldfn = window.onload; if (typeof window.onload != function) window.onload = fn; else window.onload = function() oldfn(); fn(); ; 这样,就可以随心所欲地增加新的load事件处理函数了,如下:addLoadListener(firstFunction);addLoadListener(secondFunction);addLoadListener(twentyThirdFunction);讨 论JavaScript包括了给事件增加或删除监听器的方法,看上去有点像普通的事件处理,但却允许多个监听器订阅同一个元素的同一个事件的消息。不幸的是,在Internet Explorer中这种监听器的语法与在其他浏览器中的语法完全不同,IE使用一种独有的方式,而其他浏览器则完全按照W3C标准来实现。开发者将经常处于这种折磨之中,在第13章将会讨论有关的细节。W3C标准方法叫做addEventListener:window.addEventListener(load, firstFunction, false); IE的方法叫做attachEvent:window.attachEvent(onload, firstFunction);正如您所看到的,标准的创建方法是,直接使用事件的名字(没有on前缀),事件发生时需要调用的函数以及一个用于控制事件传递的参数放在事件名字的后面(第13章会有更详细的讨论)。IE的方法则使用事件处理者的名字(前面带有一个on前缀),需要调用的函数的名字放在其后。在将代码组织到一起的时候,还需要测试一下试图调用的方法是否存在。可以用JavaScript的typeof操作符,它可以区分数据的不同类型(例如字符串、数字、布尔值、对象、数组、函数或者未定义类型)。一个不存在的方法会返回未定义类型。if (typeof window.addEventListener != undefined) 支持window.addEventListener还有一点稍稍复杂的地方:在Opera中,load事件可以激发来自文档对象的事件监听器,却不能激发来自窗口对象的监听器。不过如果只使用文档对象,这样的代码在老版本的Mozilla浏览器中(例如Netscape 6)又不能工作。为了处理这种问题,还必须测试一下window.addEventListener,然后是document.addEventListener,最后才是window.attachEvent。最后,对于那些根本不支持这些方法的浏览器(例如Mac IE 5),备用的方案是使用老式的链式事件处理方式,这样在事件发生时事件处理函数仍能被调用。可以动态地创建一个新的事件处理函数,当事件发生时,先调用老的事件处理函数,再调用新的事件处理函数1。File: add-load-listener.js (excerpt)var oldfn = window.onload;if (typeof window.onload != function) window.onload = fn;else window.onload = function() oldfn(); fn(); ; 如果您现在对这些代码怎样工作还不太理解,不用担心,后续章节还会讨论更多的细节。后面大家会了解到事件监听器不仅适用于load事件,也适用于任何事件驱动的脚本。1.9 隐藏JavaScript源代码如果您曾经创造过让自己骄傲的东西,您就会明白自己的智力成果是需要保护的。但是JavaScript是一种自然的源码开放的语言,它以源代码的方式被浏览器接收,所以,只要浏览器可以运行它,任何人也就可以阅读它。网上有些程序宣称提供对源代码的加密,但其实没有什么加密方法能够保证别人无法解密。实际上,这些程序往往会造成麻烦,它们会重新格式化代码,这让代码运行更慢、更低效,甚至会因为错误而不能运行。想知道我的建议吗?干脆碰都不要碰那些所谓的加密程序。不过,为了保护代码成果,有件事情是很容易做到的,那就是混淆代码,混淆后的代码非常不易阅读和理解。方 法被去除了所有的注释和非必需的空格之后的代码非常难以阅读,正如您期望的那样,从这样的代码中分离出功能模块更加困难。这种简单的压缩代码的方法可以让大部分黑客放弃读下去的打算,除了少数非常有毅力的黑客。如下:File: obfuscate-code.js (excerpt)var oldfn = window.onload;if (typeof window.onload != function) window.onload = fn;else window.onload = function() oldfn(); fn(); ;可以通过去掉一些非必要的空格从而将代码压缩成两行:File:obfuscate-code.js (excerpt)var oldfn=window.onload;if(typeof window.onload!=function)window.onload=fn;elsewindow.onload=function()oldfn();fn();不过,还要注意,去除的是非必需的空格。一些空格是必需的,如var和typeof之后的空格。讨 论除了混淆本身带来的好处,这种去除了注释和非必要空格的代码通常会更加简短,因此载入速度会更快,执行速度也会更快。但要注意,仍需要准确而严格地使用分号结束符和括号,就像在1.6节中讨论过的,否则,去除了换行符之后,代码被集中到一行会造成错误。在压缩代码之前,要记住先备份一个拷贝。我知道这其实是很显然的事情,不过我曾经犯过好多次错误,您一定能想象我面对一团乱麻般的代码时的郁闷。我通常的做法是维护一个有注释和足够多空格的易读的版本,然后在发布之前,通过搜索/替换来处理一番。我会保留两个拷贝,一个叫做myscript.js,另一个叫做myscript-commented.js。第20章将回到这个主题,讨论一些相关技术,从而提高脚本的速度和效率,同时降低开销。1.10 脚本调试调试是一个查错改错的过程。绝大多数浏览器拥有内建的报告错误的功能,还有一些外部的调试工具也值得关注。1.10.1 理解浏览器内建的错误报告Opera、Mozilla浏览器(例如FireFox)以及Internet Explorer都拥有很好的内建的错误报告功能,不过Opera和Mozilla的调试工具最为有用。(1)Opera 通过菜单ToolsAdvancedJavaScript console可以打开JavaScript控制台。也可以把它设置为遇到错误的时候自动打开,方法是依次选择ToolsPreferencesAdvancedContent菜单项,单击JavaScript选项按钮,打开一个对话框,然后选中Open JavaScript console on error选项。(2)FireFox和其他的Mozilla浏览器 通过菜单ToolsJavaScript console打开JavaScript控制台。(3)Internet Explorer for Windows 依次选择ToolsInternet OptionsAdvanced,然后将Disable script debugging选项前的勾取消,再选中Display a notification about every script error选项。这样,每次发生错误就会弹出一个对话框。(4)Internet Explorer for Mac 依次选择ExplorerPreferenceWeb BrowserWeb Content菜单项,然后选中Show scripting error alerts选项。Safari在默认情况下是不包括错误报告的,不过新版本有了一个“隐藏”的调试菜单,包括一个JavaScript控制台,可以通过如下的终端命令来激活1:$ defaults write com.apple.safari IncludeDebugMenu -bool true 也可以使用一种叫做Safari Enhancer1的扩展,这种扩展包含了一个选项,可以将JavaScript错误信息输出到Mac OS的控制台;但是,这些信息常常都没太大用处。理解不同浏览器报告的错误信息需要一点练习,因为每种浏览器给出的信息都不相同。这里给出一个例子一个错误类型的函数调用:function saySomething(message) alert(message);saySometing(Hello world);FireFox给出了非常简要但却很准确的报告,包括了发生错误的行号以及具体描述,如图1.1所示。图1.1 Firefox中的JavaScript错误控制台如图1.2所示,Opera给出了一个非常详细的报告,包括产生错误的回溯信息和发生错误的行号,以及具体描述。图1.2 Opera中的JavaScript控制台回溯信息有助于定位由别的代码引发的错误,例如,事件处理者调用一个函数,该函数再调用第二个函数,在这个位置发生了错误。Opera的控制台能够回溯出调用过程并找到错误最初发生时的函数调用或事件处理。Internet Explorer给出了非常基本的信息,如图1.3所示。它提供了发生错误的行号(不过可能与真实的错误位置有偏差)1,还有一个很概括的错误类型描述,但是却没有指出具体的错误。图1.3 Windows IE中的JavaScript控制台我对Internet Explorer给出的很简略的错误报告并没有太多的抱怨,至少比没有好,我知道有错误发生了。1.10.2 使用alert分析错误的时候,使用alert函数是一种非常有用的方法,可以在任何位置用它来显示对象或者变量的值,看是否是您所期望的值。例如,如果有一个有很多条件分支的函数,可以在每个分支使用alert,看看到底哪条分支被执行了:File:debugging-dialogs.jsfunction checkAge(years) if (years = 13 & years = 21) alert(13 to 21); 其他脚本 else alert(older); 其他脚本 也许传入的years根本就不是一个数字,不像函数期望的那样。可以在这段代码的开头加入一个alert,看看究竟什么类型的变量被传了进来:function checkAge(years) alert(typeof years); 从理论上说,可以用alert对话框显示任意多的信息,虽然一个非常长的串会使得弹出的对话框非常宽,以至于超出了屏幕窗口的限制而被截断。可以给输出的信息加上换行符“n”来避免这种情况。1.10.3 使用try-catchtry-catch具有令人难以置信的力量,可以做某种尝试,然后就能够处理可能发生的任何错误了。最基本的形式如下:File:debugging-trycatch.js (excerpt)try 一些代码catch (err) 如果try块中发生了错误,这部分代码将会运行如果无法确定哪里发生了错误,可以用一个try-catch的套将一大块代码包起来,并且处理最可能的错误,然后一点点缩小包围圈。例如,可以将一个函数的部分包在try语句中,然后看看哪里发生了错误。然后将嫌疑代码再分割,在适当的位置使用try套,这个过程持续下去,直到锁定出问题的那一行。catch有一个参数(在这个例子中将它命名为err)是用来接收错误对象的,我们可以通过检查这个对象的属性,例如名字和信息,来得到这个错误的具体细节。通常,我会用一个for-in语句来遍历整个对象,看看它究竟包含了什么信息:File:debugging-trycatch.js (excerpt)for (var i in err) alert(i + : + erri);1.10.4 向页面和窗口中写入数据如果在调试的时候需要检查很多数据,或者正在处理的数据有着很复杂的格式,则最好直接把数据写入一个页面或者一个弹出的窗口中,而不需要用许多alert对话框。如果检查的是循环中的数据,这样也避免了产生无数个对话框,要知道,这些对话框最后还得一个一个手工去关闭,这是非常麻烦的。针对这些情况,可以使用元素的innerHTML属性,将数据写入页面中。下面的例子是通过使用一个数组的内容创建一个列表,然后将它写入test div中:File:debugging-writing.js (excerpt)var test = document.getElementById(testdiv);test.innerHTML += ;for (var i = 0; i data.length; i+) test.innerHTML += + i + = + datai + ;test.innerHTML += ;如果在页面中没有足够的和方便的地方来显示数据,也可以将数据写入弹出对话框中: File:debugging-writing.js (excerpt)var win = window.open(, win, width=320,height=240);win.document.open();win.document.write();for (var i = 0; i data.length; i+) win.document.write( + i + = + datai + )win.document.write();win.docume
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年永新县公安局面向社会公开招聘辅警笔试参考题库附答案解析
- 2025国家体育总局体育科学研究所招聘社会在职人员2人笔试模拟试题及答案解析
- 2025年康复医学运动康复评估模拟考试卷答案及解析
- 2025年9月江西面向校内招聘干事9人笔试备考试题及答案解析
- 2025年感染病学流行病学调查方法考核模拟考试卷答案及解析
- 安徽地区中石油2025秋招笔试模拟题含答案市场营销与国际贸易岗
- 临夏回族自治州中石化面试半结构化模拟题30问附高分答案
- 国家能源江门市2025秋招面试专业追问及参考综合管理岗位
- 安阳市中石化2025秋招笔试模拟题含答案炼油设备技术岗
- 校园安全校长培训讲座课件
- 2025年省盐业投资控股集团有限公司招聘笔试备考试题带答案详解
- 钢管桩施工土建方案范例
- 保安三级安全考试题库及答案解析
- 市场仿真花施工方案
- 2025年入团知识考试题库(含答案)
- 职业培训项目实施方案
- 破产重整程序中金融债权人保护问题研究
- 视力残疾康复服务规范
- HG T 3690-2022 工业用钢骨架聚乙烯塑料复合管
- 医院医保科绩效考核标准
- 《直播营销与运营》PPT商品选择与规划
评论
0/150
提交评论