《JavaScript高级程序设计》读书笔记(五)

今天看了看LESS。前端要研究的东西确实有点多,压力有点大。而且发现自己动手写代码的水平也有待提高。从今天开始理论学习要给实践让让路了,加油加油。

这篇博文总结了《JavaScript高级程序设计》的20~21章:JSON、AJAX与Comet。此外,关于CORS的部分还参考了廖雪峰的JavaScript教程。

JSON

JSON是一种数据格式。虽然有相同的语法形式,但JSON不从属于JavaScript。很多编程语言都有针对JSON的解析器和序列化器。

语法

1.JSON的语法可以表示三种类型的值:简单值、对象、数组。

2.简单值:可表示字符串、数值、布尔值和 null,但不支持 undefined。JSON字符串必须使用双引号。

3.对象:表示一组无序的键值对。没有声明变量(JSON中没有变量概念),没有末尾分号,对象属性名必须加双引号。

1
2
3
4
5
6
7
8
{
"name": "Kyon",
"age": 20,
"school": {
"name": "Wuhan University",
"major": "Software Engineering"
}
}

4.数组:表示一组有序的值的列表,可以通过数值索引来访问其中的值。

解析与序列化

5.JSON对象有两个方法:stringify()把JavaScript对象序列化为JSON字符串,parse()把JSON字符串解析为原生JavaScript值。

6.JSON.stringify()还可以接收另外两个参数:第一个参数是个过滤器(数组:结果中只包含数组列出的属性;函数:传入的函数接收两个参数,属性名和属性值,根据属性名判断如何处理属性);第二个参数控制结果中的缩进和空白符,数值表示缩进空格数,字符串被用作缩进字符。

7.toJSON:自定义序列化。

1
2
3
4
5
6
7
8
9
var person = {
"name": "Kyon",
age: 20,
toJSON: function(){
return this.name;
}
};
var jsonText = JSON.stringify(person);

8.JSON.parse()还可以接受一个参数:将在每个键值对上调用的还原函数(与JSON.stringify()的过滤函数相同)。

AJAX与Comet

Ajax 技术的核心是 XMLHttpRequest 对象(简称 XHR)。可以使用 XHR对象取得新数据,然后再通过 DOM 将新数据插入到页面中,无须刷新页面即可从服务器取得数据。

XMLHttpRequest 对象

1.用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readState === 4){
if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
console.log(xhr.responseText);
} else {
console.log('Request was unsuccessful: ' + xhr.status);
}
}
};
// GET请求
xhr.open('get', 'example.php');
xhr.send(null);
// POST请求
xhr.open('open', 'postexample.php');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
var form = document.getElementById('user-info');
xhr.send(serialize(form));
// 将ID为user-info的表单中数据序列化后发送给服务器
  • 创建XHR对象:new XMLHttpRequest();
  • open():启动一个请求以备发送。接收三个参数:请求类型(”get”、”post”等)、请求的URL、是否异步发送请求(默认是true,一定不能为false,否则必须等到服务器响应后再继续执行)。
  • send():发送请求。GET请求不需要参数,POST请求要把body部分字符串或者FormData对象传进去。

2.XHR对象的属性:

  • responseText:返回的文本;
  • status:响应的HTTP状态;

3.HTTP状态码:

  • 2xx:成功;
  • 3xx:重定向,304 Not Modified 表示请求的资源没有被修改,可以直接用浏览器缓存的版本,302 Found 表示请求的资源现在临时从不同的URI响应请求;
  • 4xx:客户端错误,403 Forbidden,404 NotFound;
  • 5xx:服务器错误,500 Internal Server Error,503 Service Unavailable。

4.XHR的 readyState 属性:表示请求/响应过程的当前活动阶段:

  • 0:未初始化;
  • 1:启动,已调用open(),未发送;
  • 2:发送,已调用send(),未收到响应;
  • 3:接收到部分响应数据;
  • 4:接收到全部响应数据。

5.readystatechange事件:readystate属性的值由一个值变成另一个值,都会触发readystatechange事件。

跨源资源共享

6.跨域安全策略:XHR对象只能访问与包含它的页面位于同一个域的资源(域名、协议、端口号都要相同)。

7.CORS(跨源资源共享):HTML5规范定义的如何跨域访问资源。当JavaScript 向外域发起请求后,浏览器收到响应后首先检查Access-Control-Allow-Origin是否包含本域。如果不是,请求失败,JavaScript 无法获取到响应的任何数据。

跨域是否成功,取决于对方服务器是否给本域设置一个正确的Access-Control-Allow-Origin

以上“简单请求”包括GET、HEAD和POST(POST的Content-Type类型仅限application/x-www-form-urlencodedmultipart/form-datatext/plain),并且不能出现任何自定义头。

对于PUT、DELETE以及其他类型如application/json的POST请求,在发送AJAX请求之前,浏览器会先发送一个OPTIONS请求(称为preflighted请求)到这个URL上,询问目标服务器是否接受:

1
2
3
4
OPTIONS /path/to/resource HTTP/1.1
Host: bar.com
Origin: http://my.com
Access-Control-Request-Method: POST

服务器必须响应并明确指出允许的Method:

1
2
3
4
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://my.com
Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS
Access-Control-Max-Age: 86400

浏览器确认服务器响应的Access-Control-Allow-Methods头确实包含将要发送的AJAX请求的Method,才会继续发送AJAX,否则,抛出一个错误。

其他跨域技术

8.图像Ping:与服务器进行简单、单向的跨域通信的一种方式。请求的数据是通过查询字符串形式发送的,而响应可以是任意内容,但通常是像素图或204响应。

对于

1
2
3
4
5
6
7
var img = new Image();
img.onload = img.onerror = function(){
console.log("Done!");
};
// onload和onerror事件处理程序指定为同一函数,请求完成时无关响应得到通知
img.src = "http://www.example.com/test?name=Nicholas";
// 请求从设置src属性那一刻开始

两个主要缺点:只能发送GET请求;无法访问服务器的响应文本。因此只能用于浏览器与服务器间的单向通信。

9.JSONP(JSON with padding):包含在函数调用中的JSON。由回调函数和数据组成。只能用GET请求,并且要求返回JavaScript。这种方式跨域实际上利用了浏览器允许跨域引用JavaScript资源。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 得到的返回
refreshPrice({"0000001":{"code":"0000001", ...}});
// 在页面中准备好回调函数
function refreshPrice(data){
var p = document.getElementById('test-jsonp');
p.innerHTML = '当前价格:' + data['0000001'].name + ":" + data['0000001'].price;
}
// 触发
function getPrice(){
var
js = document.createElement('script'),
head = document.getElementByTagName('head')[0];
self = document.getElementById('dynamic-jsonp');
if(self){
var parent = self.parentElement;
parent.removeChild(self);
}
js.id = 'dynamic-jsonp';
js.src = 'http://api.money.126.net/data/feed/0000001,1399001?callback=refreshPrice';
head.appendChild(js);
}

缺点:从其他域中加载代码执行,安全性不可靠;不易确定请求是否失败。

10.Comet:对AJAX的进一步扩展,让服务器几乎能够实时地向客户端推送数据。实现Comet的手段主要有两个:长轮询和HTTP流。所有浏览器都支持长轮询,只有部分浏览器原生支持HTTP流。

补充:轮询是指通过JavaScript启动一个定时器,然后以固定的间隔给服务器发请求,询问服务器是否有新消息。缺点:(1)实时性不够;(2)频繁请求会给服务器带来极大压力。

11.SSE(服务器发送事件):一种实现Comet交互的浏览器API,既支持长轮询,也支持HTTP流。

12.Web Sockets:目标是在一个单独的持久连接上提供全双工、双向通信。使用一种专为快速传输小数据设计的自定义协议。

安全

13.为确保通过XHR访问的URL安全,通行做法是验证发送请求者是否有权限访问响应的资源。有下列方式:

  • 要求以SSL连接来访问可以通过XHR请求的资源。
  • 要求每一次请求都要附带经过相应算法计算得到的验证码。