《JavaScript高级程序设计》Chapter17 调试+Chapter18 XML+Chapter19 E4X+Chapter20 JSON
Chapter 17 错误的处理与调试
浏览器报告的错误
- 罗列各个浏览器显示JS错误的方式。万能的F12键。
错误处理
- try-catch语句:
- o catch传入一个包含错误信息的对象(必须起个名字如error),该对象有message属性:error.message。这个属性包含了错误信息,是唯一在浏览器中通用的。实际上各个浏览器中还有对应的特有的替代属性。
- o finally子句:try-catch语句可选。finally一旦存在必须执行。例如:若3个语句中都有return语句。那么try、catch中的return将被忽略,执行finally中的return语句。一般来说,catch和finally有一个即可。
- o 错误类型(7种错误对象)。可以当错构造函数使用以构造对应错误类型的实例。可以在catch语句中对error类型进行检测,从而进一步处理:
error instanceof TypeError; - o 合理使用try-catch语句:例如用在大型的JS库中,可以将某个库函数放在try-catch语句中以处理常抛出的错误。
- throw抛出错误
- o 与try-catch配合使用,可以抛出自定义的错误类型(值)。遇到throw的时候,代码停止执行,直到try-catch处理了错误。
- o 可以抛出上一节提到的错误类型的实例,也可以通过继承Error的方式创建(创建方法见创建和继承对象一章)自定义类型(总之,是将7种错误类型的对象当做原生对象使用,并与throw结合起来)。
- o 抛出错误的时机:在合适的时候抛出带有些许自定义(的明确的)信息的错误以方便调试。
- o 抛出错误的目的在于提供错误发生原因的信息,捕获错误的目的在于避免浏览器以默认方式处理它们。
- 错误事件error
- o 没有通过try-catch处理的错误都会触发window的错误事件error。
- o onerror错误处理程序没有event对像。可以传入三个参数:错误消息、错误所在URL、错误发生行数。有用的只有错误消息。onerror使用DOM0级技术,而非DOM2事件的格式。
window.onerror = function(message, url, line){
alert(message);
}; - o 阻止浏览器报告错误的方式:try-catch处理;阻止onerror的默认处理。
- o 图像也支持error事件,主要是在src中的URL不能正确获得图像的时候。须知,在图像发生error事件的时候,图像的下载过程已经结束了。
- 处理错误的策略:错误发生的时间、位置、类型,跟踪错误的系统
- 常见的错误类型:类型转换错误、数据类型错误、通信错误(JS松散,所以通常发生在代码执行的时候)
- o 类型转换错误:
- o 数据类型错误
- o 通信错误(Ajax。与服务器的任何一次通信,都可能发生错误)
- 区分致命错误和非致命错误
- o 非致命错误:不需要打断用户
- o 致命错误:
- 把错误记录到服务器:集中报错错误日志,以便查找重要错误的原因
- 发生在判断是否相等操作符中(建议使用全等代替)
- 流控制语句,if的判断条件上使用了非布尔值,或者编程逻辑并没有很好的覆盖所有的情况。
- 与类型转换同样建议使用类型检测typeof或者instanceof进行布尔判断。
- 基本类型用typeof;对象用instanceOf检测。
- URL格式问题。encodeURIComponent()
- 服务端出现问题
- 动态加载脚本或者样式表的时候
- 不影响用户的主要任务
- 只影响页面的一部分
- 可以恢复
- 通过重复相同操作可以消除。
- 程序无法继续运行
- 影响到用户的主要操邹
- 会导致其他连带错误
调试技术
- 将消息记录到控制台
- o cosole
- o opera.postError()
- o java控制台(LiveConnect):java.lang.System.out.printIn()
- o 可以通过综合上述三种方式进行跨浏览器的操作。
- o 同样需要手动或者通过特定的代码处理步骤清理,相比alert(),不会打断程序的运行。
- 将消息记录到当前页面:在页面中开辟一小块区域,用以显示消息。当然代码发布前同样要删除。
- 抛出错误:抛出具体的错误信息
- o throw
- o assert():大型应用程序中使用。2个参数,正确的条件,费正确的时候应该输出的信息。能减少代码量,易阅读。
常见的IE错误:之所以单独讨论,是因为它给出的错误不明确。
- 书里列举了一些错误,但更重要的是它给出的一些正确或者错误的例子,适合我们实际应用的时候多留心。
- 操作终止:operation aborted.
- 无效字符:invalid character.
- 未找到成员:IE中所有的DOM对象都是以COM对象而非JS对象实现,其垃圾收集机制会导致该错误。即,在对象销毁后,又给该对象赋值。
- 未知运行时错误(Unknown runtime error):不会隐藏或者纠正诸如将块级元素插入到不恰当位置(如span标签间)的问题,而是会报错。
- 语法错误(Syntax error):常规语法错误,引用外部脚本文件,而src指向的脚本文件却不正确返回,即错误的插入到HTML中
- 系统无法找到指定资源:请求的URL超出IE限制的2083个字符
Chapter 18 JavaScript与XML
- 重点是了解一些概念,知道他们的存在,必要的时候可以扩展学习。
- XML:存储和通过因特网传输结构化数据的标准。
- DOM将XML纳入规范
浏览器对XML DOM的支持
- DOM2级动态创建XML DOM;DOM3级解析和序列化XML
- DOM2级核心涉及到,创建一个XML DOM文档(createDocument()):
var xmldom = document.implementation.createDocument("","root",null); - 将XML解析为DOM文档:DOMParser类型+parseFromString()方法
- o new DOMParser()创建实例。
- o 在上述实例的基础上调用parserFromString(),传入XML字符串和"text/xml",实现将XML解析为DOM文档。
- o 只能解析格式良好的XML,而不能解析HTML
- o 确定是否发生解析错误:try-catch确定和处理解析后的文件,确定是否有<parsererror>标签。
- 将DOM文档序列化为XML字符串:XMLSerializer类型和serializeToString()方法
- o new XMLSerializer()创建对应实例
- o 在实例的基础上调用serializeToString(),传入待序列化的DOM对象
- o 不适合打印
- o 可以序列化任何有效的DOM对象(包括HTML文档),但若将非DOM对象传入,会引发粗偶。
- IE8以及之前(永远需要特殊处理。。。)
- o 通过ActiveXObject类型实现对XMLendangered的处理。
- o 创建XML文档的实例:
- o 解析XML字符串
- o 序列化得到XML字符串
- o 加载XML文件(可以加载来自服务器的文件,与JS相似)
- 跨浏览器处理XML
- o 处理解析XML和序列化XML这两个部分
- o 显然需要进行能力检测:IE8之后的浏览器以及IE8及之前的版本的浏览器。
- 创建ActiveXObject构造函数并传入版本字符串
- 注意并不是所有版本都有效可用,需要尝试创建的每个版本的实例并观察是否有错误发生(try-catch)
- 创建DOM文档:createDocument()创建一个空文档
- 调用loadXML()方法传入XML字符串,处理完成后将被填充到上述空DOM文档中。
- 解析出错,可以查看parseError属性。通常在调用loadXML()之后、查询XML文档之前,检查是否发生错误。
- IE将这个功能内置在DOM文档中,调用element.xml实现。
- 必须与页面运行的JS代码来自同一台服务器
- 异步和同步加载方式。
- 同步方式下,调用load()可以立即检测解析错误并执行处理。方便但是由于打断原有进程,会导致程序反应慢。
- 通常使用异步加载方式,需要检测onreadystatechange事件(主要考虑编号为4的就绪状态),典型模式在PDF P546.形式很像Ajax中的某段,然而的确加载XML文件的更加公认的方式还是使用XMLHttpRequest对象。
- 上述处理方式放在调用load()语句之前,且内部不能使用this对象(考虑到安全性禁用了this)
浏览器对XPath的支持
- XPath设计用来在DOM文档中查找节点的一种手段。
- DOM3开始规范定义了在DOM中对XPath表达式求值的接口。
- IE有自己的方法。
- 所以要考虑跨浏览器的处理方式。
浏览器对XSLT的支持
- XSLT是与XML相关的技术,利用XPath将文档从一种表现形式转换成另外一种,没有正式的API,在正式的DOM规范中没有处理的信息。IE是第一个支持JS处理XSLT的浏览器。
- IE中的XSLT
- XSLTProcesser类型:其他浏览器中。一个事实标准。
- 跨浏览器使用XSLT。
Chapter 19 E4X(ECMAScript for XML)
- 顾名思义,为了增加原生的XML支持,而确立的一个ES的可选扩展。本章讨论FireFox的支持情况。
E4X类型
- 4种E4X的类型:XML、XMLList、Namespace、QName类型。
- XML类型,可以用来创建XML对象。
- 创建XML对象的方法:
- 调用构造函数:new XML()。
- 向该构造函数传入XML字符串。
- 向该构造函数传入DOM文档或者节点
- 字面量(最好用的):直接向某个变量赋予XML字面量
- 创建XML对象的方法:
- toXMLString()方法:序列化XML
- toString()方法:一般字符串的时候形成字符串,否则序列化XML
- XMLList类型,有点像NodeList,但是与XML类型有的时候差异较小。
- 创建XMLList类型
- 调用构造函数:new XMLList()
- 传入待解析的XML字符串,可以不止包含一个文档元素,会解析成XMLList(而包含一个的时候就会解析成XML,所以差别较小。)
- 加号(+)操作符组合XML对象
- 自动创建:解析较大的XML结构时可以自动创建(灵活决定该是XML还是XMLList)
- 创建XMLList类型
- 访问XMLList:
- 方括号语法
- length()方法:而不是length属性。不过同样返回元素数量。
- 与XML的较小差别体现在:XML同样有length()方法和[0]引用
- toString()/toXMLString()方法返回相同值,将其包含的XML对象序列化之后再拼接起来。
- Namespace类型,顾名思义。命名空间(前缀prefix和uri)
- 创建:调用构造函数
- 初始化:传入URI或者前缀加URI可以初始化
- prefix和uri属性
- 自动创建namespace:XML中包含命名空间信息的时候。此时可以通过前缀以及namespace()函数取得引用(形如:xml.namespace("wrox"))。
- toString():返回URI
- Qname类型,限定名,命名空间+内部名称(本地名称,元素名等)
- 创建:构造函数
- 初始化:传入参数。本地名称。或者Namespace对象和本地名称
- uri和localName属性:只读,不可更改。
- toString(),返回形如:uri::localName的字符串
- 自动创建QName对象:XML中包含本地名称的信息的时候。此时可以通过name()方法获取QName对象的引用,以进行进一步的操作。
- setName():修改限定名
- setLocalName():不属于任何命名空间的情况下,修改内部名称。
一般用法
- 比较简单,是点操作符与“*”号的各种配合使用。同时设置了一些方法专门进行访问某些类型的对象。
- 需要的时候查书。
Chapter 20 JSON
- 是一种数据格式,并不是编程语言。
- 读写结构化数据的方式。
- 不属于JS,许多编程语言都有其解析器和序列化器。
语法
- 3种数据类型:简单值、对象、数组。
- 没有变量的概念:值就直接写出,不需要分号结尾。
- 简单值:"5"或者"Hello world"。实际操作中,更多的变现为复杂的数据结构,而简单值只是其中一部分。
- 对象:相比于JS的对象,要求属性名必须用双引号,没有分号:
{
"name":"Nicholas",
"age" : 29,
"school":{
"name":dfdf,
"location": north
}
} - 数组:[25,"hi",true]。同样没有变量和分号的概念,其中元素同样可以是复杂数据类型。
- JSON的对象和数组通常是最外层形式,通过他们可以创造处各种数据结构。
解析与序列化
- 特别容易解析成JS对象并使用(而不是需要通过DOM作为中间来调用)
- 序列化方法(JS序列化成JSON对象)JSON.stringify()方法。输出的JSON字符串不包含任何空格字符或者缩进。所有函数和原型成员都被忽略,而无效值也跳过。
- 解析方法(JSON字符串解析成JS值)JSON.parse()方法。eval()也可以,但是由于eval()本身有风险,一般不用。若传入的不是有效的JSON字符串,则会报错。
- JSON.stringify()、JSON.parse()根据传入的参数还可以有其他的用法,可以改变过滤的方法或者序列化的方法。具体查书。