第18章 JavaScript与XML
曾几何时,XML一度成为存储和通过因特网传输结构化数据的标准。此前,由于浏览器无法解析XML数据,很多开发人员都要动手编写自己的XML解析器。而自从DOM出现后,所有浏览器都内置了对XML的原生支持(XML DOM),同时也提供了一系列相关的技术支持。
浏览器对XML DOM的支持:
(1)DOM2级核心
支持DOM2级的浏览器中创建一个空白的、文档元素为<root>的XML文档:
var xmldom = document.implementation.createDocument(“”,”root”,null);
(2)DOMParser类型
为了将XML解析为DOM文档,浏览器引入了DOMParser类型。在解析XML之前,首先必须创建一个DOMParser实例,然后再调用parseFromString()方法。
(3)XMLSerializer类型
功能:将DOM文档序列化为XML字符串
(4)IE8及之前版本中的XML
事实上,IE是第一个原生支持XML的浏览器,而这一支持是通过ActiveX对象实现的。
load()可以同步或异步加载xml文档,onreadystatechange事件处理程序中readyState为4表示已经完全加载。
虽然可以通过XML DOM文档对象加载XML文件,但公认的还是使用XMLHttpRequest对象比较好。
(5)跨浏览器处理XML
浏览器对XPath的支持:
XPath是设计用来在DOM文档中查找节点的一种手段,因而对XML处理也很重要。
(1)DOM3级XPath
(2)IE中的XPath
(3)跨浏览器使用XPath
浏览器对XSLT的支持:
XSLT是与XML相关的一种技术,它利用XPath将文档从一种表现形式转换成另一种表现形式。没有正式的API。
(1)IE中的XSLT
(2)XSLTProcessor类型
(3)跨浏览器使用XSLT
第19章 E4X
2002年,由BEA Systems为首的几家公司建议为ECMAScript增加一项扩展,以便在这门语言中添加原生的XML支持。
E4X的类型:
作为对ECMAScript的扩展,E4X定义了如下几个新的全局类型:
1.XML:XML结构中的任何一个独立的部分;
2.XMLList:XML对象的集合;
3.Namespace:命名空间前缀与命名空间URI之间的映射;
4.QName:由内部名称和命名空间URI组成的一个限定名。
(1)XML类型:
Var x = new XML();
XML类型的toXMLString()方法会返回XML对象及其子节点的XML字符串表示。
(2)XMLList类型:
XMLList类型表现XML对象的有序集合。
(3)Namespace类型:
E4X中使用Namespace对象来表现命名空间。
(4)QName类型:
QName类型表现的是XML对象的限定名,即命名空间与内部名称的组合。
一般用法:
(1)访问特性
(2)其他节点类型
E4X定义了表现XML文档中所有部分的类型,包括注释和处理指令。
(3)查询
实际上,E4X提供的查询语法在很多方面都与XPath类似。
(4)构建和操作XML
(5)解析和序列化
(6)命名空间
其他变化:
第20章 JSON
JSON是JavaScript的一个严格的子集,利用了JavaScript中的一些模式来表示结构化数据。
关于JSON,更重要的是要理解它是一种数据格式,不是一种编程语言。很多编程语言都有针对JSON的解析器和序列化器。
语法:
JSON的语法可以表示以下三种类型的值:简单值、对象、数组。
(1)简单值
字符串、数值、布尔值和null。不支持undefined。
JavaScript字符串与JSON字符串的最大区别在于,JSON字符串必须使用双引号。
(2)对象
JSON中的对象要求给属性加引号,也不用声明变量。
(3)数组
JSON的数组也不用声明变量。
解析和序列化:
JSON之所以流行,拥有与JavaScript类似的语法并不是全部原因,更重要的一个原因是,可以把JSON数据结构解析为有用的JavaScript对象。
(1)JSON对象
早期的JSON解析器基本上就是使用JavaScript的eval()函数。ECMAScript 5对解析JSON的行为进行规范,定义了全局对象JSON。
JSON对象有两个方法:stringfy()和parse()。
在序列化JavaScript对象时,所有函数及原型成员都会被有意忽略,不体现在结果中。此外,值为undefined的任何属性也都会被跳过。
(2)序列化选项
实际上,JSON.stringfy()除了要序列化的JavaScript对象外,还可以接收两个参数,第一个参数是个过滤器,可以是一个数组,也可以是一个函数。第二个参数是一个选项,表示是否在JSON字符串中保留缩进。
(3)解析选项
JSON.parse()方法也可以接收另一个参数,该参数是一个函数,将在每个键值对上调用。
小结:
JSON是一个轻量级的数据格式,可以简化表示复杂数据结构的工作量。
第21章 Ajax与Comet
Ajax,是对Asynchronous JavaScript+XML的简写。这一技术能够向服务器请求额外的数据而无须卸载页面,会带来更好的用户体验。
Ajax技术的核心是XMLHttpRequest对象(简称XHR),这是由微软首先引入的一个特性。XHR为向服务器发送请求和解析服务器响应提供了流畅的接口。
XMLHttpRequest对象:
IE7+都支持原生XHR对象:var xhr = new XMLHttpRequest();
(1)XHR的用法
在使用XHR对象时,要调用的第一个方法是open,它接收3个参数:要发送请求的类型(“get”、“post”)、请求的URL和表示是否异步发送请求的布尔值。调用open()方法并不会真正发送请求,而只是启动一个请求以备发送。
调用send()方法来发送请求,接收一个参数,即要作为请求主体发送的数据。
如果这次请求是同步的,JavaScript代码会等到服务器响应之后再继续执行。在收到响应后,响应的数据会自动填充XHR对象的属性:
responseText:作为响应主体被返回的文本;
responseXML:保存包含着响应数据的XML DOM文档;
Status:响应的HTTP状态;
statusText:HTTP状态的说明。
如果是异步请求,可以检测XHR对象的readyState属性,该属性表示请求/响应过程的当前活动阶段。这个属性的值如下:
0:未初始化,尚未调用open()方法;
1:启动,已经调用open()方法,但尚未调用send()方法;
2:发送,已经调用send()方法,但尚未接收到响应;
3:接收,已经接收部分响应数据;
4:完成,已经接收全部响应数据,而且可以在客户端使用了。
只要readyState属性的值由一个值变成另一个值,都会触发一次readystatechange事件。
另外,在接收到响应之前还可以调用xhr.abort()方法来取消异步请求。
(2)HTTP头部信息
使用setRequestHeader()方法可以设置自定义的请求头部信息,接收两个参数:头部字段的名称和值。必须在调用open()方法之后且调用send()方法之前调用。
调用XHR对象的getResponseHeader()方法并传入头部字段名称,可以取得相应的响应头部信息。
(3)GET请求
对XHR而言,位于传入open()方法的URL末尾的查询字符串必须经过正确的编码才行。查询字符串中每个参数的名和值都必须使用encodeURIComponent()进行编码。
(4)POST请求
默认情况下,服务器对POST请求和提交Web表单的请求并不会一视同仁。不过,我们可以使用XHR来模仿表单提交:首先将Content-Type头部信息设置为application/x-www-form-urlencoded,也就是表单提交时的内容类型。
从性能角度看,以发送相同的数据统计,GET请求的速度最多可达到POST请求的两倍。
XMLHttpRequest 2级:
(1)FormData
现代Web应用中频繁使用的一项功能就是表单数据的序列化,XMLHttpRequest 2级为此定义了FormData类型。FormData为序列化表单以及创建与表单格式相同的数据(用于通过XHR传输)提供了便利。
Var data = new FormData(); data.append(“name”,”Nicholas”);
使用FormData的方便之处在于不必明确在XHR对象上设置请求头部,XHR对象能够识别传入的数据类型是FormData的实例,并配置适当的头部信息。
(2)超时设定
IE8为XHR对象添加了一个timeout属性,表示请求在等待响应多少毫秒之后会终止,触发timeout事件,进而会调用ontimeout事件处理程序。
(3)overrideMimeType()方法
Firefox最早引入了overrideMimeType()方法,用于重写XHR响应的MIME类型。
进度事件:
进度事件定义了与客户端服务器通信有关的事件,有以下6个进度事件:
loadstart:在接收到响应数据的第一个字节时触发;
Progress:在接收响应期间持续不断的触发;
error:在请求发生错误时触发;
Abort:在因为调用abort()方法而终止连接时触发;
load:在接收到完整的响应数据时触发;
Loadend:在通信完成或者触发error、abort或load事件后触发。
(1)load事件
Firefox实现中引入了load事件,用以替代readystatechange事件。响应接收完毕后将触发load事件,因此就没必要去检查readystate属性了。
(2)progress事件
Onprogress事件处理程序会接收到一个event对象,其target属性是XHR对象,但包含着三个额外的属性:lengthComputable、position和totalSize。其中lengthComputable是一个表示进度信息是否可用的布尔值,position表示已经接收的字节数,totalSize表示根据Content-Length响应头部确定的预期字节数。
在调用open()方法之前添加onprogress事件处理程序。
跨域资源共享:
通过XHR实现Ajax通信的一个主要限制,来源于跨域安全策略。
CORS(跨域资源共享)是W3C的一个工作草案,定义了在必须访问跨域资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想,就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。
比如:在发送请求时附加一个额外的Origin头部,如果服务器认为这个请求可以接受,就在Access-control-allow-origin头部中回发相同的源信息。
(1)IE对CORS的实现
IE8引入了XDR类型,这个对象与XHR类似,但能实现安全可靠的跨域通信。
(2)其他浏览器对CORS的实现
都通过XMLHttpRequest对象实现了对CORS的原生支持。要请求位于另一个域中的资源,使用标准的XHR对象并在open()方法中传入绝对URL即可。
(3)Preflighted Requests
CORS通过一种叫做Preflighted Request的透明服务器验证机制支持开发人员使用自定义的头部、GET或POST之外的方法,以及不同类型的主体内容。
(4)带凭据的请求
默认情况下,跨域请求不提供凭据。通过将withCredential属性设置为true,可以指定某个请求应该发送凭据。如果服务器接受带凭据的请求,会用下面的HTTP头部来响应。
Access-Control-Allow-Credentials:true
(5)跨浏览器的CORS
检测XHR是否支持CORS的最简单方式,就是检查是否存在withCredentials属性。
其他跨域技术:
在CORS出现以前,要实现跨域Ajax通信颇费一些周折。开发人员想出了一些办法,利用DOM中能够执行跨域请求的功能,在不依赖XHR对象的情况下也能发送某种请求。
(1)图像Ping
var img = new Image();
img.src = “http://www.jinjumao.club?name=aaa”;
图像Ping最常用于跟踪用户点击页面或动态广告曝光次数。图像Ping有两个主要的缺点,一是只能发送GET请求,二是无法访问服务器的响应文本。
(2)JSONP
JSONP是通过动态<script>元素来使用的,使用时可以为src属性指定一个跨域URL。
与图像Ping相比,它的优点在于能够直接访问响应文本,支持浏览器与服务器之间双向通信。
(3)Comet
Comet指的是一种更高级的Ajax技术(经常也有人称为“服务器推送”)。Ajax是一种从页面向服务器请求数据的技术,而Comet则是一种服务器向页面推送数据的技术。非常适合处理体育比赛的分数和股票报价。
(4)服务器发送事件
SSE(服务器发送事件)API用于创建到服务器的单向连接,服务器通过这个连接可以发送任意数量的数据。
Var source = new EventSource(“my events.php”);
该实例有一个readyState属性,值0表示正连接到服务器,值1表示打开了连接,值2表示关闭了连接。另外还有3个事件,open、message、error。
(5)Web Sockets
Web Sockets的目标是在一个单独的持久连接上提供全双工、双向通信。
send()方法向服务器发送数据,当服务器向客户端发来消息时,websocket对象就会触发message事件,返回的数据保存在event.data属性中。
(6)SSE与Web Sockets
选择SSE还是web sockets时,可以考虑几个因素:(1)SSE通过HTTP通信,现有的服务器可以满足,Web Sockets要建立Web Sockets服务器。(2)如果只需读取服务器数据(如比赛成绩)用SSE就够了,要实现双向通信(如聊天室)则要用Web Sockets。组合使用XHR和SSE也是能实现双向通信的。
安全:
对于未被授权系统有权访问某个资源的情况,我们称之为CSRF(跨站点请求伪造)。
为确保通过XHR访问的URL安全,通行的做法就是验证发送请求者是否有权限访问相应的资源:
1.要求以SSL连接来访问可以通过XHR请求的资源。
2.要求每一次请求都要附带经过算法计算得到的验证码。
请注意,下列措施对防范CSRF攻击不起作用:
1.要求发送POST请求而不是GET请求—很容易改变;
2.检查来源URL以确定是否可信—来源记录很容易伪造;
3.基于cookie信息进行验证—同样很容易伪造。
小结:
Ajax是无需刷新页面就能够从服务器取得数据的一种方法。