JavaScript高級程序設計(第三版)學習筆記20、21、23章


第20章,JSON

JSON(JavaScript Object Notation,JavaScript對象表示法),是JavaScript的一個嚴格的子集。
JSON可表示一下三種類型值:
簡單值:字符串,數值,布爾值,null,不支持js特殊值:undefined
對象:一組無序的鍵值對
數組:一組有序的值的列表
不支持變量,函數或對象實例
注:JSON的字符串必須使用雙引號,這是與JavaScript字符串最大的區別

對象

{
     "name":"Nicholas",
     "age":20
}
注:JSON中的對象要求給屬性加引號
與JavaScript不同,沒有聲明變量,末尾不用分號
對象嵌入:
{
    "name":"Nicholas",
    "age":19,
    "school":{
        "name":"school",
        "location":"location"
    }
}

數組

采用js的數組字面量形式:
[21,"hi",true]
注:JSON數組也沒有分號和變量
數組嵌入
[
    {
        "title":"array",
        "author":"author"
    },
    [
        "title":"book",
        "author":{
            "nameOne",
            "nameTwo"
        }
    ]
]

JSON對象

早期的JSON解析器基本上使用的是js的eval函數。ECMAScript5定義了全局對象JSON,支持的瀏覽器:IE8+,Firefox3.5+,Safari4+,Chrome,Opera10.5+。
JSON對象的兩個方法:stringify,parse。最簡單情況,分別用於把js對象序列化為JSON字符串和把JSON字符串解析成原生js值
var book = {
    title:"title",
    author:[
        "Nicholas C. Zakas"
    ],
    edition:3,
    year:2011
};
var jsonText = JSON.stringify(book);
alert(jsonText);          //{"title":"title","author":["Nicholas C. Zakas"],"edition":3,"year":2011}
注:默認情況下JSON.stringify輸出的JSON字符串不包含任何空格字符或縮進。
序列化時所有函數和原型成員都會被忽略,值為undefined的屬性也會被跳過。
JSON.parse過程相反,傳遞的字符串不是有效JSON,會拋出錯誤

序列化選項

JSON.stringify還可以接收另外兩個參數:1、過濾器,可以是數組,也可以是函數。2、選項,表示是否在JSON字符串保留縮進

1、過濾結果

若過濾器是數組,則JSON.stringify結果將只包含數組列出的元素
var book = {
    title:"title",
    author:[
        "Nicholas C. Zakas"
    ],
    edition:3,
    year:2011
};
var jsonText = JSON.stringify(book,["title","edition"]);     //{"title":"title","edition":3}

如果是函數,則又有不同

var jsonText = JSON.stringify(book,function(key,value){
    switch(key){
        case "author":
            return value.join(",");
           
        case "year":
            return 5000;

        case "edition":
            return undefined;
        default:
            return value;
    }
});                                   //{"title":"title","author":"Nicholas C. Zakas","year":5000}

2、字符串縮進

JSON.stringify第三個參數用於控制縮進和空白符,若是數值,表示每個級別的縮進空格數
var jsonText = JSON.stringify(book,null,4);
//結果:
{
    "title": "title",
    "author": [
        "Nicholas C. Zakas"
    ],
    "edition": 3,
    "year": 2011
}
注:最大縮進空格數為10,大於10的數值全部轉為10
若縮進參數是字符串,則將被用於縮進字符
{
- -"title": "title",
- -"author": [
- - - -"Nicholas C. Zakas"
- -],
- -"edition": 3,
- -"year": 2011
}
注:最大縮進字符數不能超過10,超過的將只顯示前10個字符

3、toJSON方法

toJSON方法可以作為函數過濾器的補充,理解序列化順序:
1、如果存在toJSON方法,而且能通過它取得有效值,調用該方法,否則返回對象本身
2、若提供了第二個參數,應用這個函數過濾器,傳入函數過濾器的值是第一步返回值
3、對第二步返回值進行序列化
4、若提供了第三個參數,執行相應格式化

解析選項

JSON.parse也接收另一個參數,是一個函數,將在每個鍵值對上調用。若返回結果為undefined,表示刪除該值,返回其他值,則將該值插入到結果。
var book = {
    title:"title",
    author:[
        "Nicholas C. Zakas"
    ],
    edition:3,
    year:2011,
    releaseDate:new Date(2011,11,1)
};

var jsonText = JSON.stringify(book);
var bookCopy = JSON.parse(jsonText,function(key,value){
    if(key == "releaseDate"){
        return new Date(value);
    }else{
        return value;
    }
});

alert(bookCopy.releaseDate.getFullYear());               //2011

第21章,Ajax和Comet

Ajax核心是XMLHttpRequest對象,能夠以異步的方式從服務器獲取更多信息,意味着用戶單擊后,可以不必刷新頁面也能取得數據

XMLHttpRequest

IE7+,Firefox,Opera,Chrome,Safari都支持原生的XHR對象,創建對象:
var xhr = new XMLHttpRequest();
瀏覽器兼容
function createXHR(){
    if(typeof XMLHttpRequest != "undefined"){
        return new XMLHttpRequest;
    }else if(typeof ActiveXObject != "undefined"){
        if(typeof arguments.callee.activeXString != "string"){
            var versions = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"],i,len;
            for(i=0,len=versions.length;i < len;i++){
                try{
                    new ActiveXObject(versions[i]);
                    arguments.callee.activeXString = versions[i];
                    break;
                }catch(ex){
                    //跳過
                }
            }
        }
        return new ActiveXObject(arguments.callee.activeXString);
    }else{
        throw new Error("No XHR Object available");
    }
}
//使用示例
var xhr = createXHR();

XHR用法

第一個方法:open,接收3個參數:
1、要發送的請求的類型(“get”,“post”)
2、請求的URL
3、表示是否異步發送請求的布爾值
xhr.open("get","example.php",false);
說明:1、url相對於執行代碼的當前頁面(也可以使用絕對路徑),2、並不會真正發送請求,而是啟動一個請求以備發送
使用send方法發送:
xhr.send(null);
send接受一個參數:作為請求主體發送的數據,不需要則要傳入null。響應的數據會被填充到XHR對象的屬性。屬性簡介:
responseText:作為響應主體被返回的文本
responseXML:響應內容類型若是"text/xml"或"application/xml",將保存包含着響應數據的XML DOM文檔
status:響應的HTTP狀態
statusText:HTTP狀態說明
接到響應后,首先檢查status屬性,可以將HTTP狀態碼200,作為成功的標志,狀態碼304表示請求資源並沒有修改,可以直接使用瀏覽器中緩存的版本。
xhr.open("get","example.php",false);               //同步請求
xhr.send(null);

if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
    alert(xhr.resopnseText);
}else{
    alert("Request was unsuccessful: "+xhr.status);
}
異步請求,檢查readyState屬性,表示請求/響應過程的當前活動階段,取值:
0:未初始化,尚未調用open
1:啟動,已調用open,未調用send
2:發送,已調用send,未收到響應
3:接收,已接收部分數據
4:完成,接收全部數據,已經可以在客戶端使用了
必須在調用open之前指定onreadystatechange事件處理程序才能確保跨瀏覽器兼容性:
var xhr = createXHR();
xhr.onreadystatechange = function(){                         //DOM0級方法,不是所有瀏覽器都支持DOM2級方法
    if(xhr.readyState == 4){
        if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
            alert(xhr.resopnseText);
        }else{
            alert("Request was unsuccessful: "+xhr.status);
        }
    }
};
xhr.open("get","example.php",true);                         //異步請求
xhr.send(null);

在接收到響應之前還可以調用abort方法來取消異步請求:

xhr.abort();

HTTP頭部信息

默認情況下,發送XHR請求的同時,還會發送下列頭部信息
Accept:瀏覽器能夠處理的內容類型
Accept-Charset:瀏覽器能夠顯示的字符集
Accept-Encoding:瀏覽器能夠處理的壓縮編碼
Accept-Language:瀏覽器當前設置語言
Connection:瀏覽器與服務器之間的鏈接類型
Cookie:當前頁面設置的熱河Cookie
Host:發出請求的頁面所在的域
Referer:發出請求的頁面的URI。注:HTTP規范把這個頭部字段拼錯了,應該是referrer
User-Agent:瀏覽器的用戶代理字符串
以上列出的基本上是所有瀏覽器都會發送的。可以通過setRequestHeader方法設置自定義的請求頭部信息。接收兩個參數:頭部字段名稱,頭部字段值,要成功發送請求頭部信息,必須在調用open方法之后,調用send方法之前調用setRequestHeader
var xhr = createXHR();
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
            alert(xhr.resopnseText);
        }else{
            alert("Request was unsuccessful: "+xhr.status);
        }
    }
};
xhr.open("get","example.php",true);
xhr.setRequestHeader("MyHeader","MyValue");
xhr.send(null);
調用XHR對象的getRequestHeader方法並傳入頭部字段名稱,可以取得相應頭部信息,調用getAllResponseHeaders()方法則可以獲得一個包含所有頭部信息的長字符串。

GET請求

使用GET請求經常發生的一個錯誤,就是查詢字符串的格式有問題,查詢字符串的每個參數的名稱和值都必須使用 encodeURIComponent()(第五章提到的通用資源標識符編碼)進行編碼,然后才能放到URL末尾,而且所有鍵-值對都必須使用和號(&)分隔。

POST請求

通常用於向服務器發送應該保存的數據,應該把數據作為請求的主體提交,可以包含非常多的數據,且格式不限。
若需要將頁面中的表單數據進行序列化,然后通過XHR放到服務器,則可以使用14章的serialize函數來創建字符串:
function submitData(){
    var xhr = createXHR();
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4){
            if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
                alert(xhr.resopnseText);
            }else{
                alert("Request was unsuccessful: "+xhr.status);
            }
        }
    };

    xhr.open("post","postExample.php",true);
    xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    var form = document.getElementById("user-info");
    xhr.send(serialize(form));
}

示例php文件:

<?php
    header("Content-Type:text/plain");
    echo <<<EOF
    Name:{$_POST['user-name']}
    Email:{$_POST['user-email']}
    EOF;
?>
如不設置Content-Type頭部信息,要訪問同樣信息必須借助$HTTP_RAW_POST_DATA
XMLHttpRequest2級
定義FormData類型,為序列化表單以及創建與表單格式相同的數據(用於通過XHR傳輸)提供了便利。
方法1、
var data = new FormData();
data.append("name","Nicholas");          //接收兩個參數:鍵,值

方法2、

var data = new FormData(document.forms[0]);     //直接使用表單元素

方法3、

var form = document.getElementById("user-info");
xhr.send(new FormData(form));
支持的瀏覽器:Firefox4+,Safari5+,Chrome,Android3+,WebKit

超時設定

IE8為XHR添加了timeout屬性,表示請求等待多少毫秒之后終止,在寫作JavaScript高級程序設計第三版時,IE8+仍然是唯一支持超時設定的瀏覽器

overrideMimeType方法

Firefox最早引入overrideMimeType方法,用於重寫XHR響應的MIME類型。因為返回響應的MIME類型決定了XHR如何處理它。
支持的瀏覽器Firefox,Safari4+,Opera10.5,Chrome

進度事件

Progress Events規范是W3C的一個工作草案,定義了與客戶端服務器通信有關的事件,最早針對XHR操作,目前也被其他API借鑒,6個進度事件:
loadstart:接收到響應數據第一個字節觸發
progress:接收響應期間持續不斷地觸發
error:請求錯誤觸發
abort:調用abort方法觸發
load:接收到完整的響應數據觸發
loadend:通信完成或觸發error,abort,load事件后觸發

跨源資源共享

IE對CORS的支持

CORS(Cross-Origin Resource Sharing,跨源資源共享)是W3C的一個工作草案
IE8中引入了XDR(XDomainRequest)類型,與XHR類似,但能實現安全可靠的跨域通信。與XHR不同:
1、cookie不會隨請求發送,也不會隨請求返回
2、只能設置頭部信息中的Content-Type
3、不能訪問響應頭部信息
4、只支持GET和POST請求
使用方法,也是創建一個XDomainRequest實例,調用open,調用send,open方法只接受兩個參數,請求類型,URL。所有請求都是異步。

其他瀏覽器對CORS的支持

Firefox3.5+,Safari4+,Chrome,ios版Safari,Android平台中的WebKit都通過XHR對象實現了對CORS的原生支持。
限制:
1、不能使用setRequestHeader
2、不能發送和接收cookie
3、調用getAllResponseHeaders會返回空字符串

其他跨域技術

圖像ping

JSONP

Comet

Comet一種更高級的Ajax技術。Ajax是從頁面向服務器請求數據的技術,Comet是服務器向頁面推送數據的技術。能夠讓信息近乎實時的被推送到頁面上。

服務器發送事件

SSE(Server-Sent Events,服務器發送事件)是圍繞只讀Comet交互推出的API或者模式

Web Socket

使用標准的HTTP服務器無法實現Web Socket,只有支持這種協議的專門服務器才能工作。
支持瀏覽器:Firefox6+,Safari5+,Chrome,ios4+版Safari

1、Web Socket API

要創建Web Socket,先實例一個WebSocket對象並傳入要連接的URL
var socket = new WebSocket("ws://www.example.com/server.php");
注:必須傳入絕對URL
表示當前狀態的readyState屬性:
WebSocket.OPENING(0):正在建立連接
WebSocket.OPEN(1):已建立連接
WebSocket.CLOSING(1):正在關閉連接
WebSocket.CLOSE(3):已關閉
關閉Web Socket連接:
socket.close();

2、發送和接收數據

socket.send("hello world");          //任意字符串
只能發送純文本數據,發雜結構的數據要經過序列化。

3、其他事件

open:成功建立連接觸發
error:發生錯誤觸發,連接不能持續
close:連接關閉觸發

第23章,離線應用與客戶端存儲

離線檢測

H5定義了navigator.onLine屬性,true表示能上網。
H5還定義了兩個事件:online(離線變在線觸發),offline(在線變離線觸發),在window對象上觸發。

應用緩存

要在緩存中保存數據,可以使用描述文件

數據存儲

HTTP Cookie,通常叫做cookie。

1、限制

在性質上是綁定在特定域名下的。

2、cookie的構成

cookie由瀏覽器保存的以下幾塊信息構成
名稱:唯一確定cookie的名稱,不缺分大小寫,實踐中最好看成區分大小寫。
值:儲存在cookie中的字符串值,必須被URI編碼
域:對於哪個域有效
路徑:對於域中的那個路徑,應該向服務器發送cookie
失效時間:cookie應該被刪除的時間
安全標志:指定后,cookie只有在使用ssl連接時才發送到服務器

3、js中的cookie

在js中處理cookie有些復雜,因為眾所周知的蹩腳的接口,即BOM的document.cookie屬性
基本的cookie操作:讀,寫,刪,在CookieUtil對象表示:
var socket = new WebSocket("ws://www.example.com/server.php");
var CookieUtil = {
    get:function(name){
        var cookieName = encodeURIComponent(name) + "=" ,
            cookieStart = document.cookie.indexOf(cookieName),
            cookieValue = null;

        if(cookieStart > -1){
            var cookieEnd = document.cookie.indexOf(";",cookieStart);
            if(cookieEnd == -1){
                cookieEnd = document.cookie.length;
            }
            cookieValue = decodeURIComponent(document.cookie.substring(cookieStart+cookieName.length,cookieEnd));
        }

        return cookieValue;
    },
    set:function(name,value,expires,path,domain,secure){
        var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value);

        if(expires instanceof Date){
            cookieText += "; expires=" + expires.toGMTString();
        }
        if(path){
            cookieText += "; path=" + path;
        }
        if(domain){
            cookieText =+ "; domain=" + domain;
        }
        if(secure){
            cookieText += "; secure=" + secure;
        }
        document.cookie = cookieText;
    },
    unset:function(name,path,domain,secure){
        this.set(name,"",new Date(0),path,domain,secure);
    }
};

使用示例:

//設置cookie
CookieUtil.set("name","Nicholas");
CookieUtil.set("book","Professional JavaScript");

//讀取
alert(CookieUtil.get("name"));  //"Nicholas"
alert(CookieUtil.get("book"));  //Professional JavaScript

//刪除
CookieUtil.unset("name");
CookieUtil.unset("book");

//設置cookie,包括它的路徑、域、失效日期
CookieUtil.set("name","Nicholas","/books/projs","www.wrox.com",new Date("January 1,2010"));

//刪除剛設置的cookie
CookieUtil.unset("name","/books/projs","www.wrox.com");

//設置安全cookie
CookieUtil.set("name","Nicholas",null,null,null,true);

4、子cookie

為了繞開瀏覽器的單域名下cookie數量限制

5、關於cookie的思考

盡量少存儲信息,不存敏感信息

Web存儲機制

Web Storage目的是克服由cookie帶來的一些限制。主要目的:
1、提供一種cookie之外存儲會話數據的途徑;
2、提供一種存儲大量可以跨會話存在的數據的機制
Web Storage包含了兩種對象定義:sessionStorage,globalStorage,支持瀏覽器:IE8+,Firefox3.5+,Chrome4+,Opera10.5+

1、Storage類型

注:Storage類型只能存字符串,不是字符串的會被轉換成字符串

2、sessionStorage對象

數據值保存到瀏覽器關閉

3、globalStorage對象

目的:跨越會話存儲數據,有特定的訪問限制。
數據保留到js刪除或用戶清除瀏覽器緩存

4、localStorage對象

要訪問同一個localStorage對象,頁面必須來自同一域名(子域名無效),使用同一種協議,在同一個端口
數據保留到js刪除或用戶清除瀏覽器緩存

5、storage事件

對Storage對象的任何修改,都會在文檔上觸發storage事件

IndexedDB

在瀏覽器中保存結構化數據的一種數據庫
操作完全異步
1、數據庫
open方法,存在就打開,不存在就創建並打開
2、對象存儲空間
3、事務
4、使用游標查詢
在對象存儲空間調用openCursor方法卡創建游標
5、鍵范圍
通過游標查找方式有限,鍵范圍為游標增添了靈活性
6、設定游標方向
7、索引
8、並發問題
9、限制
與Web Storage類似,只能由同源(同協議,域名,端口)頁面操作,不能跨域共享信息。
空間限制


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM