20. JSON

2006年,Douglas CrockFord, JSON(JavaScript Object Notation)js对象表示法

  • JSON语法可以表示以下三种类型的值
    • 简单值:字符串、数值、布尔值、null,但是不支持undefined
    • 对象:无序键值对
    • 数组:有序值列表
  • JSON字符串全部用双引号!!!
  • JSON对象属性名必须加引号!!!
  • 解析
    • 早期使用eval()
    • ES5定义了全局对象JSON
      • stringify()
      • parse()
    • 所有函数及原型成员都会被忽略,不体现在结果中
    • 值为undefined的属性会被跳过
  • JSON.stringify(obj, filter, option)
  • toJSON方法 —> 如果有该方法,JSON.stringify()会执行该方法
var book = {
	title: 'Professional JavaScript',
	authors: ["Nicholas C. Zakas"],
	edition: 3,
	year: 2011
};
console.log(JSON.stringify(book));
console.log(JSON.stringify(book, ['title', 'authors']));
console.log(JSON.stringify(book, null, 4));
console.log(JSON.stringify(book, null, "----"));

21. Ajax和comet

Asynchronous JavaScript and XML能够向服务器请求额外的数据,而无需卸载页面。

21.1 XMLHttpRequest

  • xhr.open('get', '/api', asyncBoolean);
  • xhr.send(null);
  • 响应
    • responseText
    • responseXML
    • status
    • statusText
  • XHR.readyState
    • 所有可能取值:
      • 0 未初始化
      • 1 启动open
      • 2 发送send
      • 3 接收
      • 4 完成
    • readystatechange事件
    • setRequestHeader()
    • getResponseHeader()
    • getAllResponseHeaders()
  • HTTP头部信息
    • 请求头部
      • Accept
      • Accept-Charset
      • Accept-Encoding
      • Accept-Language
      • Connection
      • Cookie
      • Host 发出请求的页面所在的域
      • Referer 发出请求的页面的URI
      • User-Agent浏览器的用户代理字符串
  • GET
    • 查询字符串中每个参数的名称都必须使用encodeURIComponet()进行编码
function addURLParam(url, name, value){
	url += url.includes('?') ? '&' : '?';
	url += encodeURIComponent(name) + '=' + encodeURIComponet(value);
	return url;
}
  • POST
    • POST比GET更安全,因为参数不会被保存在浏览器历史或web服务器中。
    • application/x-www-form-urlencoded

21.2 XHR 2

  • FormData
    • append()
  • 超时设定
    • XHR.timeout = 1000
  • overrideMimeType()

21.3 进度事件Process Events

  • 6个进度事件:(简化异步交互模型)
    • loadstart/progress/error/abort/load/loadend
    • onprocess: lengthComputable/position/totalSize

21.4 跨域资源共享CORS

默认情况下,XHR只能访问与包含它的页面位于同一个域内的资源
CORS定义了在必须访问跨域资源时,浏览器应该如何与服务器沟通。
CORS背后的基本思想,就是使用自定义的HTTP头部,让浏览器与服务器进行沟通,从而决定请求或响应是否成功。

  • 同源策略:为通信设置“同域,同端口,同协议”的限制
  • IE8引入了XDR(XDomainRequest)
    • cookie不随请求发送,也不随响应返回
    • 只能设置请求头部的Content-Type
    • 不能访问响应头部信息
    • 只支持GET和POST
  • CSRF(cross-site Request Forgery)跨站请求伪造
    • 未被授权的系统有权访问某个资源
    • 解决方案:SSL连接、每次请求附带验证
    • cookie信息验证不能防范CSRF攻击
  • XSS(Cross-Site Scripting)跨站脚本攻击
    • 为了不和CSS混淆
  • Access-Control-Allow-Origin
  • Preflighted Requests透明服务器验证机制
    • OPTIONS方法请求头部
      • Origin
      • Access-Control-Request-Method
      • Access-Control-Request-Headers
    • 响应头部
      • Access-Control-Allow-Origin
      • Access-Control-Allow-Methods
      • Access-Control-Allow-Headers
      • Access-Control-Max-Age
  • 带凭据的请求
    • 默认情况下,跨源请求不提供凭据(Cookie、HTTP认证及客户端SSL证明)
    • 通过设置withCredentialstrue,可以指定某个请求应该发送凭据
    • Access-Control-Allow-Credentials: true
  • 其他跨域技术
    • 图像Ping

      一个网页可以从何网页中加载图像,不受跨域影响,这是在线广告跟踪浏览量的主要方式。
      图像Ping只能用于浏览器对服务器的单向通信

    • JSONP
      • JSONP是JSON with padding,填充式JSON或参数式JSON
      • http://xxx.net/json/?callback=handleResponse
      • 通过查询字符串指定JSONP服务的回调函数
      • <script><img>都有能力不受限制的跨域加载资源
      	function handleResponse(response){
      		console.log(response)
      	}
      	var script = document.createElement("script");
      	script.src = " http://219.216.80.193:3000/menus?callback=handleResponse";
      	document.body.insertBefore(script, document.body.firstChild);
      
    • Comet服务器推送
      • Ajax是一种从页面向服务器请求数据的技术;而comet是一种服务器向页面推送数据的技术
      • 有两种实现Comet的方式:长轮询和流
      • 长轮询是传统轮询(短轮询)的一个翻版。
        • 短轮询即浏览器定时向服务器发送请求,看有没有更新的数据。
        • 长轮询是页面发起一个请求到服务器,然后服务器一直保持连接打开,直到有数据可发送。
        • 短轮询是服务器立即发送响应,无论数据是否有效。长轮询是一直等待一个有效响应。
      • HTTP流,在页面的整个生命周期内只有一个HTTP连接
        • 浏览器发送一个请求,服务器保持连接打开,然后周期性地向浏览器发送数据。
      • SSE(server-sent events 服务器发送事件)只读Comet
        • 到服务器的单向连接text/event-stream
        • var src = new EventSource("myEvents.php");
      • Web Sockets
        • 目标是在一个单独的持久连接上提供全双工的双向通信
        • URL模式:ws://
        • 使用自定义协议的好处是,能够在客户端和服务器之间发送非常少量的数量,而不用担心HTTP那样字节级的开销。
        • var socket = new WebSocket(url);
        • readyState/close()