您的位置:首页 > Web前端 > JavaScript

js笔记--JSON,Ajax

2016-07-28 15:43 513 查看

1.JSON语法

JSON是一种数据格式,并不是一种编程语言。虽然与JavaScript具有相同的语法形式,但JSON并不从属于JavaScript。
JSON不支持变量,函数或对象实例,它就是一种表示结构化数据的格式

1.语法

简单值: 字符串,数值,布尔和null。不支持JavaScript中的特殊值undefined
对象:作为复杂数据类型,表示的是一组有序的键值对。每个键值对的值可以是简单类型也可以是复杂类型
数组:表示一组有序的值的列表,可以通过数值索引来访问其中的值
JSON字符串必须使用双引号(单引号会导致语法错误)

2.对象

JSON中对象与JavaScript字面量稍微有一些不同

JavaScript中的对象字面量:

var person = {
name:"ethan",
age:25
};
JSON对象:

{
"name":"ethan",
"age":28
}
对象的属性必须加双引号

3.数组

JavaScript数组:
var values = [25,"hi",true];

JSON数组:

[25,"hi",true]


2.解析与序列化

1.JSON对象

早期使用eval()函数解析并返回JavaScript对象。
现在通过JSON全局对象来解析json

stringify():

将JavaScript对象序列化为JSON字符串

parse():

将JSON字符串解析为原生JavaScript值

在序列化JavaScript对象时,所有函数及原型成员都会被忽略。此外,值为undefined的任何属性也会被跳过。结果中最终都是值为有效JSON数据类型的实例属性。

2.序列化选项

JSON.stringify()除了接收要序列化的JavaScript对象外,还可以接收另外两个参数。一:过滤器,可以是一个数组,也可以是一个函数;二:一个选项,表示 是否在JSON字符串中保留缩进。

1.过滤结果

如果过滤器参数是数组,那么JSON.stringify()的结果中将只包含数组中列出的属性 

var person = {
name:"zhangsan",
"age":34,
"hobbit":["football","basketball",'volleyball'],
son:{
name:"李四",
age:10
}
};

var json = JSON.stringify(person,["name","age"]);
console.log(json);// {"name":"zhangsan","age":34}


如果过滤参数是函数
var json = JSON.stringify(person,function(key,value){
switch(key){
case "name":
return value;
case "age":
return undefined;//跳过指定的属性
case "hobbit":
return value.join(",");
default:
return value;
}
});
console.log(json);// {"name":"zhangsan","hobbit":"football,basketball,volleyball","son":{"name":"李四"}}

2.字符串缩进

JSON.stringify()方法的第三个参数控制结果中的缩进和空白符。

var person = {
name:"zhangsan",
"age":29,
hobbit:["basketball","sing","eat"],
son:{
name:"lisi",
age:4
}
};
var json = JSON.stringify(person,null,2);
console.log(json);
输出格式如下:
{
"name": "zhangsan",
"age": 29,
"hobbit": [
"basketball",
"sing",
"eat"
],
"son": {
"name": "lisi",
"age": 4
}
}

最大缩进空格数为10,超过10就取10

缩进字符串参数:  自负串替代空格

var json = JSON.stringify(person,null,"- -");
console.log(json);
{
- -"name": "zhangsan",
- -"age": 29,
- -"hobbit": [
- -- -"basketball",
- -- -"sing",
- -- -"eat"
- -],
- -"son": {
- -- -"name": "lisi",
- -- -"age": 4
- -}
}


3.toJSON()方法

有时候JSON.stringify()并不能满足对某些对象进行自定义序列化的需求。这种情况下,可以通过对象上调用toJSON()方法,返回自身的JSON数据格式。原生Date对象有一个toJSON()方法,将JavaScript的Date对象自动转换成ISO 8601日期字符串(与Date上调用toISOString()结果一样)。

var person = {
name:"zhangsan",
"age":34,
"hobbit":["football","basketball",'volleyball'],
son:{
name:"李四",
age:10
},
toJSON:function(){ //自定义json转换方法
return this.name;
}
};
var jsonText = JSON.stringify(person);
console.log(jsonText); //zhangsan


toJSON()可以作为函数过滤器的补充,对象序列化顺序如下:

如果存在toJSON()方法且能通过它取得有效的值,则调用该方法。否则,按默认顺序执行序列化
如果提供了第二个参数,应用这个函数过滤器。传入函数过滤器的值是第(1)步返回的值
对第(2)步返回的值进行序列化
如果提供了第三个参数,执行相应的格式化

3.解析选项

JSON.parse()方法可以接受一个参数,该参数是一个函数,在每个键值对上调用。称为(reviver)还原函数

如果函数返回undefined,表示从结果中删除相应的键;如果返回其他值,表示将该值插入到结果中。

var person = {
name:"zhangsan",
"age":34,
"hobbit":["football","basketball",'volleyball'],
son:{
name:"李四",
age:10
},
birthday:new Date(2016,6,8)
};
var jsonText = JSON.stringify(person);
console.log(jsonText);
var personCopy = JSON.parse(jsonText,function(key,value){
if(key == 'birthday'){ //否则返回日期字符串
return new Date(value);
}else{
return value;
}
});
console.log(personCopy);


3.XMLHttpReques对象

1.XHR用法

open():接收三个参数,请求方式(get,post等),请求URL,是否异步发送请求


并不会真正发送请求,只是启动一个请求以备发送。只能向同一个域中使用相同端口和协议的URL发送请求。

send():发送请求,一个参数(要发送的请求数据)。在收到响应后,响应的数据会自动填充XHR对象的属性

responseText:作为响应主体被返回的文本,无论内容类型是什么。
responseXML:如果响应内容是"text/xml"或"application/xml",这个属性中将保存包含着响应数据的XML DOM文档。
status:响应的HTTP状态
statusText:HTTP状态说明
<span style="white-space:pre">	</span>var xhr = new XMLHttpRequest();
// console.log(xhr);
xhr.open("post","....url...",false);
xhr.send(null);
if((xhr.status >=200 && xhr.status<300)||xhr.status ==304){
// console.log(xhr.responseText);
console.log(xhr.status);
}else{
console.log("request fail");
}


发送异步请求(JS继续执行不必等待响应)。通过检测XHR的readyState属性来判断响应状态

0:未初始化,尚未调用open()方法
1:启动。已经调用open()方法
2:发送。已经调用send()方法
3:接收。已经接收到部分响应数据
4:完成。已经接收到全部响应数据,可以在客户端使用

readyState属性值变化都会触发readystatechange事件。必须在open()方法调用前指定onreadystatechange事件处理程序才能保证跨浏览器兼容性。

var xhr = new XMLHttpRequest();
//检测状态变化
xhr.onreadystatechange = function(){
console.log(xhr.readyState);
if(xhr.readyState == 4){//响应完成
if((xhr.status >=200 && xhr.status<300)||xhr.status ==304){
// console.log(xhr.responseText);
console.log(xhr.status);
}else{
console.log("request fail");
}
}
}
// console.log(xhr);
xhr.open("post",".....",false);
xhr.send(null);
在接收响应之前可以调用abort()方法来取消异步请求
xhr.abort();

2.HTTP请求消息头

XHR提供setRequestHeader(key,value)来操作http请求消息头

Accept:浏览器能处理的内容类型
Accept-Charset:浏览器能显示的字符集
Accept-Encoding:浏览器能处理的压缩编码
Accept-Language:浏览器当前设置的语言
Connection:浏览器与服务器之间连接的类型
Cookie:当前页面设置的任何Cookie
Host:发出请求的页面所在的域
Referer:发出请求的页面URL(防止盗链)
User-Agent:浏览器的用户代理字符串
必须在open()之后,send()之前调用setRequestHeader()
getResponseHeader();获取响应头对应的信息
getAllResponseHeader():获取包含所有头部信息的长字符串
var xhr = new XMLHttpRequest();
//检测状态变化
xhr.onreadystatechange = function(){
console.log(xhr.readyState);
if(xhr.readyState == 4){//响应完成
if((xhr.status >=200 && xhr.status<300)||xhr.status ==304){
var allHeaders = xhr.getAllResponseHeaders();
console.log(allHeaders);
}else{
console.log("request fail");
}
}
}
xhr.open("post","wgps/tmsweb/showDomesticRoute.action?referenceCode=HTM201607170132201",false);
xhr.setRequestHeader("MyHead","hehe");
xhr.send(null);


3.get请求方式

查询字符串参数追加到URL末尾发送给服务器。对XHR而言,位于传入open()的URL末尾的查询字符串必须经过正确的编码才行
每个参数的名称和值都必须使用encodeURIComponent()进行编码
function addURLParam(url,name,value){
url += (url.indexOf("?")== -1 ? '?':'&');
url += encodeURIComponent(name)+"="+encodeURIComponent(value);
return url;
}


4.post请求

send():向服务器发送数据,作为请求的主体提交。

由于XHR最初的设计主要是为了处理XML,因此可以传入XML DOM文档,传入的文档经序列化之后将作为请求主体被提交到服务器。当然,也可以在此传入任何想发送到服务器的字符串

默认情况下,服务器对POST请求和提交Web表单的请求不会一视同仁。因此服务器端必须有程序来读取发送过来的原始数据,并从中解析出有用的部分。
可以使用XHR模仿表单提交。将Content-Type头部信息设置为application/x-www-form-urlencoded(表单提交时的内容类型),然后提交表单序列化后的格式参数。

<span style="white-space:pre">	</span>xhr.open("post","....",true);
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(serialize(form));
与GET请求相比,POST请求消耗的资源会更多。从性能角度看,发送相同的数据,GET请求的速度最多可达到POST请求的两倍。

4.XMLHttpRequest 2级

1.FormData

FormData为序列化表单以及创建与表单格式相同的数据(用于通过XHR传输)提供了便利。
键值对

var data = new FormData();
data.append("name","zhangsan");
直接构造函数传入表单

var data = new FormData(document.forms[0]);
不必设置请求头。XHR对象能识别传入的数据类型是FormData的实例

xhr.send(new FormData(document.forms[0]));


2.超时设定

XHR对象timeout属性,请求在等待响应指定毫秒后就终止。如果在规定时间内没有接收到响应,就会触发timeout事件,进而调用ontimeout事件处理程序。

<span style="white-space:pre">	</span>var xhr = new XMLHttpRequest();
//检测状态变化
xhr.onreadystatechange = function(){
console.log(xhr.readyState);
if(xhr.readyState == 4){//响应完成
try{
if((xhr.status >=200 && xhr.status<300)||xhr.status ==304){
var allHeaders = xhr.getAllResponseHeaders();
console.log(allHeaders);
}else{
console.log("request fail");
}
}catch(err){
console.log(err);
}
}
}
xhr.open("post","...",true);
xhr.timeout = 1000;//将超时设置为1秒
xhr.ontimeout = function(){
console.log("请求超时");
}
xhr.send(null);
如果1秒钟内没有返回就会自动终止。readyState变为4,触发onreadystatechange事件处理程序。超时后再访问status属性,会导致报错。

所以将status检测的代码放到try-catch语句中

3.overrideMimeType()方法

用来重写XHR响应的MIME类型。必须在send()方法前

xhr.overrideMimeType("text/xml");
xhr.send(null);


5.进度事件

loadstart:接收到响应数据的第一个字节时触发
progress:接收响应期间持续不断地触发
error:请求发生错误时触发
abort:在调用abort()方法终止连接时触发
load:在接收到完整响应数据时触发
loadend:在通信完成或触发error,abort或load时间后触发
从触发loadstart事件开始,接下来是一个或多个progress事件,然后触发error,abort或load事件中的一个,最后触发loadend事件结束

1.load事件

用来替代readystatechange事件,响应接收完毕后触发load事件,不用检查readyState属性。
而onload事件处理程序会接收到一个event对象,target属性就指向XHR对象实例

var xhr = new XMLHttpRequest();
xhr.onload = function(event){
console.log(event.target);//XHR对象
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
console.log("success"+xhr.status);
}else{
console.log("fail"+xhr.status);
}
}
xhr.open("get","...",true);
xhr.send(null);
只要浏览器接收到服务器响应。不管状态如何,都会触发load事件

2.progress事件

在浏览器接收新数据期间周期性地触发。onprogress事件处理程序会接收到一个event对象,target属性是XHR对象,包含三个额外属性:
lengthComputable:进度信息是否可用
position:已经接收的字节数
totalSize:根据Content-Length响应头消息确定的预期字节数

可以给用户创建一个进度指示器

xhr.onprogress = function(event){
var divStatus = document.getElementById("editDiv");
if(event.lengthComputable){
divStatus.innerHTML = "received"+event.position+" of " +event.totalSize +"bytes";
}
}
必须在调用open()方法之前添加onprogress事件处理程序

6.跨资源共享

CORS(Cross-Origin Resource Sharing,跨源资源共享),定义了在必须访问跨源资源时,浏览器与服务器应该如何沟通。使用自定义HTTP头部让浏览器与服务器沟通。
比如一个简单的使用GET或POST发送的请求,没有自定义头部,主体内容是text/plain。在发送请求时,需要给它附加一个额外的Origin头部,其中包含请求页面的资源信息(协议,域名,和端口),一般服务器根据这个头部信息来决定是否给予响应。
Origin:http://www.baidu.com

如果服务器认为这个请求可以接受,就在Access-Control-Allow-Origin头部中回发相同的源信息(如果是公共资源,可以回发"*").
Access-Control-Allow-Origin:http://www.baidu.com

如果没有这个头部,或这个头部信息不匹配,浏览器会驳回请求。正常情况下,浏览器会处理请求,但请求和响应不包含cookie信息。

当使用XMLHttpRequest发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin;浏览器判断该相应头中是否包含Origin的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据 

1.IE对CORS的实现

XDR(XDomainRequest)。该对象与XHR类似。部分实现了CORS规范

cookie不会随请求发送,也不会随响应返回
只能设置请求头中的Content-Type字段
不能访问响应头部信息
只支持GET和POST请求
所有XDR请求都是异步执行,请求返回后会触发load事件,响应数据保存在responseText属性。

2.其他浏览器对CORS的实现

Firefox3.5+,Safari4+,Chrome通过XMLHttpRequest对象实现了对CORS的原生支持,跨域访问不需要额外代码,在open()中传入绝对URL即可。

      apache服务器  :http://localhost/      上的html

var xhr = new XMLHttpRequest();
// console.log(xhr);
xhr.onload = function(event){
console.log(event.target);//XHR对象
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
console.log(xhr.responseText);
}else{
console.log("fail"+xhr.status);
}
}
xhr.open("post","http://localhost:8080/wgps/servlet/CROSServlet",false);//访问tomcat上的servlet
xhr.send(null);

报错:
XMLHttpRequest cannot load http://localhost:8080/wgps/servlet/CROSServlet. No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost'
is therefore not allowed access.
在tomcat服务器端,设置响应消息头的属性
response.setHeader("Access-Control-Allow-Origin", "http://localhost");

就可以正常实现跨域访问

XHR对象可以访问status和statusText属性,并且支持同步请求。同时也有如下限制:

不能使用setRequestHeader()设置自定义头部
不能发送和接收cookie
调用getAllResponseHeaders()方法总会返回空字符串
在访问本地资源时,最好使用相对URL,避免出现限制访问头部或本地cookie信息等问题。

3.Preflighted Requests

CORS通过Preflighted Requests的透明服务器验证机制支持开发人员使用自定义的头部,GET或POST之外的方法,以及不同类型的主体内容。
向服务器发送一个Preflight请求,这种请求使用OPTIONS方法。

Origin:与简单请求相同。
Access-Control-Request-Method:请求自身使用的方法
Access-Control-Request-Headers:(可选)自定义的头部信息,多个信息以逗号分隔。

7.其他跨域技术

在CORS出现以前,要实现跨域Ajax通信颇费一些周折。利用DOM中能够执行跨域请求的功能,在不依赖XHR对象的情况下也能发送某种请求。

1.图像Ping

使用<img>标签。一个网页可以从任何网页中加载图像,不用担心跨域问题。这也是在线广告跟踪浏览量的主要方式。可以动态地创建图像,使用它们的onload和onerror事件处理程序来确定是否接收到了响应。

动态创建图像经常用于图像Ping。图像Ping是与服务器进行简单,单向的跨域通信的一种方式。
请求的数据通过查询字符串形式发送,响应可以是任意内容,通常是像素图或204响应。
通过图像Ping,浏览器得不到任何具体的数据,但通过侦听load和error事件,能知道响应是什么时候接收到的

var img = new Image();
img.onload = function(){
console.log("done!");
}
img.onerror = function(){
console.log("error!");
}
img.src = "http://www.baidu.com";

2.JSONP

JSONP是JSON with  padding(填充式JSON或参数式JSON)的简写,是应用JSON的一种新方法。JSONP看起来与JSON差不多,只不过是被包含在函数调用中的JSON,如:
callback({"name":"zhangsan"});
由两部分组成:1.回调函数,当响应到来时应该在页面中调用的函数,一般在请求中指定回调函数的名字。

2.数据,传入回调函数中的JSON数据。

function handleResponse(response){
console.log(response);
}
var script = document.createElement("script");
script.src = "http://localhost:8080/wgps/tmsweb/queryFreightOrderByPage.action?callback=handleResponse";
document.body.insertBefore(script,document.body.firstChild);


 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: