1. 程式人生 > >JS當中的Ajax非同步互動(詳細筆記)

JS當中的Ajax非同步互動(詳細筆記)

Ajax
1. Ajax
是Asynchronous JavaScript and XML的縮寫,非同步的JavaScript和XML. Ajax描述了一種主要使用指令碼操作HTTP的Web應用架構,Ajax應用的主要特點是使用指令碼操縱HTTP和Web伺服器進行資料交換,不會導致頁面過載。

2. HTTP
    超文字傳輸協議(HyperText Transfer Protocol)規定了Web瀏覽器如何從Web伺服器獲取文件和向Web伺服器提交表單內容,以及Web伺服器如何響應這些請求和提交。通常,HTTP並不在指令碼的控制下,只是當用戶單擊連結,提交表單和輸入URL時才發生。但是,用JavaScript程式碼操縱HTTP是可行的。
    1) HTTP請求組成
        HTTP請求方法或動作
        正在請求的URL
        請求頭集合,其中可能包含身份驗證資訊(可選)
        請求體(可選)
    2) HTTP響應
        一個數字和文字組成的返回碼,用來顯示請求的成功和失敗
        一個響應頭集合
        響應體

3. XMLHttpRequest
    瀏覽器在XMLHttpRequest類上定義了它們的HTTP API,這個類的每個例項都表示一個獨立的請求/響應對,並且這個物件的屬性和方法允許指定請求細節和提取響應資料。很多年前Web瀏覽器就開始支援XMLHttpRequest,並且其API已經到了W3C指定標準的最後階段。同時W3C正在指定“2級XMLHttpRequest”標準草案。
    在使用XMLHttpRequest時,必須將html部署到web伺服器中。

    1) 指定請求
        1. 例項化
            var request = new XMLHttpRequest();
            request為例項化的XMLHttpRequest物件,該物件可以重用,但是這將會終止之前通過該物件掛起的任何請求。

        2. 指定請求
            open()
            引數:
                1.指定HTTP方法或動作,這個字串不區分大小寫,通常大家用大寫字母來匹配HTTP協議。取值可以為:GET/POST/HEAD/DELETE/OPTIONS/PUT 
                    GET :用於常規請求,適用於URL完全指定的請求資源,請求對伺服器沒有任何副作用,伺服器的響應是(可快取)的
                    POST:用於HTML表單,它在請求主體中包含額外資料,且這些資料常儲存到伺服器上的資料庫中。相同URL的重複POST請求從伺服器得到的響應可能不同,同時(不應該緩)存使用這個方法的請求。
                2.URL,請求的主題,是相對於文件的URL。跨域請求會報錯。
                3.Boolean型別的值,如果值為false代表同步請求,send()方法將阻塞直到請求完成。這種情況下無需使用事件處理函程式,一旦send()返回,只需檢查XMLHttpRequest物件的status和responseText屬性。
            request.open("GET","data.xml");

        3. 設定請求頭
            setRequestHeader();
            如果有請求頭,需要呼叫該方法進行設定。
            引數:
                1.key
                2.value

            request.setRequestHeader("Content-type","text/plain;charset=UTF-8");
            //json資料格式
            request.setRequestHeader("Content-Type","application/json");
            注意:
                XMLHttpRequest將自動新增以下這些請求頭以防止偽造,我們無法向setRequestHeader()傳遞以下請求頭。
                Accept-Charset      TE              Content-Transfer-Encoding
                Accept-Encoding     Date            Trailer
                Connection          Expect          Transfer-Encoding
                Content-Length      Host            Upgrade
                Cookie              Keep-Alive      User-Agent
                Cookie2             Referer         Via
        4. 指定可選的請求主體並向伺服器傳送
            send()
            引數:
                請求主體內容,如果沒有,為null,或者省略。

        /*
          使用POST方法提交純文字給伺服器
        */
        function postMessage(url,msg){
            var request = new XMLHttpRequest();
            request.open("POST",url);
            request.setRequestHeader("Content-type","text/plain;charset=UTF-8");
            request.send(msg);
        }

    2) 取得響應  (request屬性)
    HTTP狀態碼  
        status      以數字number形式返回HTTP狀態碼    200(ok) 404  伺服器找不到  403 跨域訪問報錯
        500  後臺程式碼異常
        statusText  以文字string形式返回HTTP狀態碼    OK  Not Found
        getResponseHeader()     獲取指定響應頭
        getAllResponseHeaders() 獲取所有響應頭
        responseText    獲取文字形式(string)的響應體
        responseXML     獲取Document形式的響應體
        JS狀態碼
        readyState      返回HTTP請求狀態
            0   open()尚未呼叫  UNSENT   還未發貨
            1   open()已呼叫       OPENED  已經發貨
            2   接收到頭資訊      HEADERS_RECEIVED 貨到了
            3   接收到響應主體     LOADING  確認收貨 
            4   響應完成            DONE   訂單完成

        【請求完成後激發的事件】
        onreadystatechange 請求狀態改變事件
            當readyState值改變為4或伺服器的響應完成時,所有的瀏覽器都觸發該事件

        /*
          獲取HTTP響應
        */
        function getText(url,callback){
            //1.例項化XMLHttpRequest
            var request = new XMLHttpRequest();
            //2.指定請求
            request.open("GET",url);
            request.onreadystatechange = function(){
                //如果請求完成,並且請求成功
                if(request.readyState === 4 && request.status ===200){
                    //3.設定請求頭
                    var type = request.getResponseHeader("Content-type");
                    if(type.match(/^text/)){    //如果響應是文字
                        callback(request.responseText);//執行回撥函式
                    }
                }
            };
            //4.傳送請求
            request.send(null);
        }
    3) 響應解碼
        1.MIME型別為text/plain,text/html,text/css 文字型別時,可以使用responseText屬性解析
        2.MIME型別為XML文件型別時,使用responseXML屬性解析
        3.如果伺服器傳送物件,陣列這樣的結構化資料作為其響應,他應該傳輸JSON編碼的字串資料。通過responseText接受到它,可以把它傳遞給JSON.parse()方法來解析。

4.編碼請求主體
    HTTP POST請求包括一個請求主體,它包含客戶端傳遞給伺服器的資料。
    1) 表單編碼的請求
        當用戶提交表單時,表單中的資料(每個表單元素的名字和值)編碼到一個字串中並隨請求傳送。對錶單資料的編碼方案:對每個表單元素的名字和值執行普通的URL編碼(使用十六進位制轉義碼替換特殊字元),使用等號把編碼後的名字和值分開,並使用"&"符號分開鍵/值對。表單資料編碼格式有一個正式的MIME型別 application/x-www-form-urlencoded(預設)

        當使用POST方式提交這種順序的表單時,必須設定"Content-Type"請求頭為"application/x-www-form-urlencoded"用於HTTP請求的編碼物件

        編碼表單資料(封裝)
        function encodeFormData(data){
            if(!data){
                return "";
            }
            var pairs = [];
            for(var name in data){
                if(!data.hasOwnProperty(name)){
                    continue;
                }
                if(typeof data[name] == "function"){
                    continue;
                }
                var value = data[name].toString();
                name = encodeURIComponent(name).replace("%20","+");//編碼名字
                value = encodeURIComponent(value).replace("%20","+");//編碼值
                pairs.push(name+"="+value);
            }
            return pairs.join('&');
        }
        name=%E6%9D%8E%E6%98%A5%E9%9B%A8+terry&passwd=110

        使用表單編碼資料發起一個HTTP POST請求
        function postData(url,data,callback){
            var request = new XMLHttpRequest();
            request.open("POST",url);
            reqeust.onreadystatechange = function(){
                if(request.readyState === 4 && callback){
                    callback(request);
                }
            };
            //設定請求頭
            request.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
            //傳送表單編碼的資料
            request.send(encodeFormData(data));
        }

        使用表單編碼資料發起GET   請求
        function getData(url,data,callback){
            var request = new XMLHttpRequest();
            request.open("GET",url+"?"+encodeFormData(data));
            reqeust.onreadystatechange = function(){
                if(request.readyState === 4 && callback){
                    callback(request);
                }
            };
            request.send(null);
        }

    2) JSON格式的編碼請求

        /*
        物件序列化
    物件序列化是指將物件的狀態轉換為字串,也可以反序列化,將字串還原為物件函式,RegExp,Error物件,undefined值不能序列化和反序列化。
    JSON.stringify(obj)  
        將物件序列化為Json字串,只能序列化物件可列舉的自有屬性。
    JSON.parse(jsonStr)  
        反序列化  將字串解析為物件
    */

        近年來,作為Web交換格式的JSON已經得到了普及。
        function postJSON(url,data,callback){
            var request = new XMLHttpRequest();
            request.open("POST",url);
            reqeust.onreadystatechange = function(){
                if(request.readyState === 4 && callback){
                    callback(request);
                }
            };

            request.setRequestHeader("Content-Type","application/json");
            request.send(JSON.stringify(data));
        }
    3) XML編碼的請求
        XML有時也用於資料傳輸的編碼,但是較少
        //doc表示一個XML DOM
        function postXML(url,doc,callback){
            var request = new XMLHttpRequest();
            request.open("POST",url);
            reqeust.onreadystatechange = function(){
                if(request.readyState === 4 && callback){
                    //var text = request.responseText;
                    var result = responseXML;
                    callback(result);
                }
            };
            //自動設定合適的頭部。
            request.send(doc);
        }
5. 中止請求和超時
    function getData(url,timeout,callback){
        var request = new XMLHttpRequest();
        var flag = false;
        var timer = setTimeout(function(){
            flag = true;
            request.abort();//中止請求
        },timeout);
        request.open("GET",url+"?"+encodeFormData(data));
        reqeust.onreadystatechange = function(){
            if(request.readyState !== 4 ){
                return;
            }
            if(timeout){
                return; //如果超時返回
            }else{
                clearTimeout(timmer); 
            }
            if(request.status === 200){
                callback(request);
            }
        };
        request.send(null);
    }

6. 跨域HTTP請求
    作為同源策略的一部分,XMLHttpRequest物件通常僅可以發起和文件具有相同伺服器的HTTP請求。可以在<form>
    ,<iframe>元素中使用跨域URL,但因為同源策略,瀏覽器不允許原始指令碼查詢跨域文件內容。
    不過我們又發現,Web頁面上呼叫js檔案時則不受是否跨域的影響
    (不僅如此,我們還發現凡是擁有”src”這個屬性的標籤都擁有跨域的能力,比如<script>、<img>、<iframe>。

    1) JSONP --json padding
        為了便於客戶端使用資料,逐漸形成了一種非正式傳輸協議,人們把它稱作JSONP,該協議的一個要點就是允許使用者傳遞一個callback引數給服務端,然後服務端返回資料時會將這個callback引數作為函式名來包裹住JSON資料,這樣客戶端就可以隨意定製自己的函式來自動處理返回資料了。
        1. js跨域訪問
            遠端伺服器下 檔案remote.js
                alert('我是遠端檔案');
            本地伺服器下 檔案jsonp.html
                <script type="text/javascript" src="http://otherHost/remote.js"></script>
            這時候會alert,說明跨域訪問呼叫成功
        2. 遠端呼叫原生代碼  
            遠端伺服器下 檔案remote.js
                localHandler({"result":"我是遠端js帶來的資料"});
            本地伺服器下 檔案jsonp.html
                var localHandler = function(data){
                    alert('我是本地函式,可以被跨域的remote.js檔案呼叫,遠端js帶來的資料是:' + data.result);
                };
                <script type="text/javascript" src="http://otherHost/remote.js"></script>
        3. 動態呼叫
            遠端伺服器下 檔案remote.js
                flightHandler({
                    "code": "CA1998",
                    "price": 1780,
                    "tickets": 5
                });
            本地伺服器下 檔案jsonp.html
                // 得到航班資訊查詢結果後的回撥函式
                var flightHandler = function(data){
                    try{
                        alert('你查詢的航班結果是:票價 ' + data.price + ' 元,' + '餘票 ' + data.tickets + ' 張。');
                    }finally{
                        script.parentNode.removeChild(script);
                    }
                };
                // 提供jsonp服務的url地址(不管是什麼型別的地址,最終生成的返回值都是一段javascript程式碼)
                //呼叫的url中傳遞了一個code引數,告訴伺服器我要查的是CA1998次航班的資訊,而callback引數則告訴伺服器,我的本地回撥函式叫做flightHandler,所以請把查詢結果傳入這個函式中進行呼叫。
                var url = "jsonp.js?code=CA1998&callback=flightHandler";
                // 建立script標籤,設定其屬性
                var script = document.createElement('script');
                script.setAttribute('src', url);
                // 把script標籤加入head,此時呼叫開始
                document.getElementsByTagName('head')[0].appendChild(script);   
        4. 封裝
            getJSONP.counter = 0;//回撥函式名稱計數器
            function getJSONP(url,callback){
                var cbnum = "cb"+getJSONP.counter++;
                var cbname = "getJSONP."+cbnum;

                if(url.indexOf("?") === -1){
                    url += "?jsonp="+cbname;
                }else{
                    url += "&jsonp="+cbname;
                }

                var script = document.createElement("script");
                //為每個請求建立了一個全新的內部回撥函式,作為getJSON函式的一個屬性儲存。
                getJSONP[cbnum]= function(response){
                    try{
                        callback(response);
                    }finally{
                        //清理工作:刪除回撥函式
                        delete getJSONP[cbnum];移除script元素
                        script.parentNode.removeChild(script);  

                    }
                }
            }

            //呼叫
            getJSONP("getAllStudents.action?clazz=1",function(response){
                //處理
                ...
            });

    2) CORS(跨域資源共享,Cross-Origin Resource Sharing)
        CORS是W3C的一個工作草案,定義了在必須訪問跨域資源時,瀏覽器和伺服器應該怎麼溝通,CORS背後的思想是使用自定義的HTTP頭部讓瀏覽器與伺服器進行溝通,從而決定請求或響應應該是成功還是失敗
            例如:
                當前域為 http://www.briup.com
            如果遠端伺服器認為這個請求可以接受,就在Access-Control-Allow-Origin頭部中回發相同的資訊
                Access-Control-Allow-Origin:http://www.briup.com
            如果沒有這個頭部,或者有這個頭部但源資訊不匹配,瀏覽器會駁回請求。
    CORS需要瀏覽器和伺服器同時支援。目前,所有瀏覽器都支援該功能,IE瀏覽器不能低於IE10。
    實現CORS通訊的關鍵是伺服器。只要伺服器實現了CORS介面,就可以跨源通訊。
3.Cookie
    CORS請求預設不傳送Cookie和HTTP認證資訊。如果要把Cookie發到伺服器,一方面要伺服器同意,指定Access-Control-Allow-Credentials欄位。
    Access-Control-Allow-Credentials: true;
    另一方面,開發者必須在AJAX請求中開啟withCredentials屬性。

    var xhr = new XMLHttpRequest();
    xhr.withCredentials = true;
    需要注意的是,如果要傳送Cookie,Access-Control-Allow-Origin就不能設為星號,必須指定明確的、與請求網頁一致的域名。同時,Cookie依然遵循同源政策,只有用伺服器域名設定的Cookie才會上傳,其他域名的Cookie並不會上傳,且(跨源)原網頁程式碼中的document.cookie也無法讀取伺服器域名下的Cookie。

附:
1. JSON
JSON能夠以非常簡單的方式來描述資料結構,XML能做的它都能做,因此在跨平臺方面兩者完全不分伯仲。以下是JSON規則:
1) JSON只有兩種資料型別描述符,大括號{}和方括號[]其餘英文冒號:是對映符,英文逗號,是分隔符,英文雙引號”“是定義符。
2) 大括號{}用來描述一組“不同型別的無序鍵值對集合”(每個鍵值對可以理解為OOP的屬性描述),方括號[]用來描述一組“相同型別的有序資料集合”(可對應OOP的陣列)。
3) 上述兩種集合中若有多個子項,則通過英文逗號,進行分隔。
4) 鍵值對以英文冒號:進行分隔,並且建議鍵名都加上英文雙引號””,以便於不同語言的解析。
5) JSON內部常用資料型別無非就是字串、數字、布林、日期、null 這麼幾個,字串必須用雙引號引起來,其餘的都不用,日期型別比較特殊,這裡就不展開講述了,只是建議如果客戶端沒有按日期排序功能需求的話,那麼把日期時間直接作為字串傳遞就好,可以省去很多麻煩。
2. 編碼方式
encodeURI 和 encodeURIComponent都是ECMA-262標準中定義的函式,所有相容這個標準的語言(如JavaScript, ActionScript)都會實現這兩個函式。它們都是用來對URI (RFC-2396)字串進行編碼的全域性函式,但是它們的處理方式和使用場景有所不同。為了解釋它們的不同,我們首先需要理解RFC-2396中對於URI中的字元分類
1) 保留字元(reserved characters):這類字元是URI中的保留關鍵字元,它們用於分割URI中的各個部分。這些字元是:”;” “/” “?” “:” “@” “&” “=” “+” “$” “,”
2) Mark字元(mark characters):這類字元在RFC-2396中特別定義,但是沒有特別說明用途,可能是和別的RFC標準相關。 這些字元是:”-” “_” “.” “!” “~” “*” “’” “(” “)”
3) 基本字元(alphanum characters):這類字元是URI中的主體部分,它包括所有的大寫字母、小寫字母和數字

在介紹完上面三類字串後,我們就非常容易來解釋encodeURI和encodeURIComponent函式的不同之處了:
    1) encodeURI: 該函式對傳入字串中的所有非(基本字元、Mark字元和保留字元)進行轉義編碼(escaping)。所有的需要轉義的字元都按照UTF-8編碼轉化成為一個、兩個或者三個位元組的十六進位制轉義字元(%xx)。例如,字元空格" "轉換成為"%20"。在這種編碼模式下面,需要編碼的ASCII字元用一個位元組轉義字元代替,在\u0080和\u007ff之間的字元用兩個位元組轉義字元代替,其他16為Unicode字元用三個位元組轉義字元代替

    2) encodeURIComponent: 該函式處理方式和encodeURI只有一個不同點,那就是對於保留字元同樣做轉義編碼。例如,字元":"被轉義字元"%3A"代替

之所以有上面兩個不同的函式,是因為我們在寫JS程式碼的時候對URI進行兩種不同的編碼處理需求。encodeURI可以用來對完整的URI字串進行編碼處理。而encodeURIComponent可以對URI中一個部分進行編碼,從而讓這一部分可以包含一些URI保留字元。這在我們日常程式設計中是十分有用的。比如下面的URI字串:
    http://www.mysite.com/send-to-friend.aspx?url=http://www.mysite.com/product.html
在這個URI字串中。send-to-friend.aspx頁面會建立HTML格式的郵件內容,裡面會包含一個連結,這個連結的地址就是上面URI字串中的url值。顯然上面的url值是URI中的一個部分,裡面包含了URI保留關鍵字元。我們必須呼叫encodeURIComponent對它進行編碼後使用,否則上面的URI字串會被瀏覽器認為是一個無效的URI。正確的URI應該如下:
    http://www.mysite.com/send-to-friend.aspx?url=http%3A%2F%2Fwww.mysite.com%2Fproduct.html 
  1. GET請求(明信片)
    a.html -> b.html
    攜帶引數:
    a.html?key1=val1&key2=val2

    瀏覽器位址列:
    getAllStudents.action?clazz=三年二班&gender=男

  2. POST提交(信)
    a.html -> b.html
    瀏覽器位址列:
    getAllStudents.action
    引數: 儲存在請求體中。

*****************回顧+note*************************
DOM
Node
document element
事件
事件流
事件繫結方法
DOM0
DOM2
事件型別
支援子元素
click
mouseover
mouseout
事件代理
遞迴
5!
function fac(num){
if(num<=1){
return 1;
}else{
return num*arguments.callee(num-1);
}
}
fac(4);

上面的方式在嚴格模式下不能使用
    fac = function f(num){
        if(num<=1){
            return 1;
        }else{
            return num*f(num-1);
        }
    };

閉包
例1
var a = 3;
a = 4;
function showA(){
alert(a);// alert(scope.a);
}
a = 5;
showA();

    showA閉包= {
        showA
        scope = {a:5}
    }
例2
    function
    <ul>
        <li>test1</li>
        <li>test2</li>
        <li>test3</li>
    </ul>
    var lis = document.getElementsByTagName(li);
    for(var i=0;i<lis.length;i++){
        lis[i].onclick = function(){
            lis[i].innerHTML = "dom"+(i+1);
        };
    }
    //解決
    for(var i=0;i<lis.length;i++){
        lis[i].onclick =(function(num){
        //函式呼叫  i被解析
            return function(){
                lis[num].innerHTML = "dom"+(num+1);
            };
        })(i);
    }
    //forEach
    將類陣列轉換陣列物件

BOM
JS是單執行緒語言

超時呼叫
    函式,在一定時間之後才去執行
    setTimeout()
    引數
        要呼叫的函式
        超時時間

間歇呼叫
    setInterval();
    引數
        要呼叫的函式
        間歇時間

函式執行
區域性變數
var a = 1; //全域性變數
function foo(){
alert(a);
var b = 2; //區域性變數
if(a>0){
var c = 3;//塊級變數
}
alert(c);
//只要在函式內部宣告的變數,在宣告之後都可以放到
}
alert(b);//訪問不到

Ajax
伺服器
Apache
htdocs 伺服器根目標
專案的部署
javascript/ajax.html
bin 啟動或關閉伺服器

將Apache伺服器開啟 80 

在瀏覽器中訪問呢
http://127.0.0.1:80/javascript/ajax.html

http://127.0.0.1:80/
        ---> htdocs/   伺服器根目錄
http://127.0.0.1:80/javascript/ajax.html
        htdocs/javascript/ajax.html

ajax.html
    data.json

路徑
相對路徑
路徑不以”/”開頭
request.open(“GET”,”data.json”);
相對於當前檔案所在目錄
當前檔案 ajax.html-> http://127.0.0.1:80/javascript/

    http://127.0.0.1:80/javascript/data.json

絕對路徑
    路徑以"/"開頭
    request.open("GET","/data.json");
    相對於伺服器根目錄
        htdocs-> http://127.0.0.1:80/
    http://127.0.0.1:80/data.json

******************Ajax-2-note*****************
1. Ajax
非同步的JavaScript 和 XML

JSON

瀏覽器與伺服器之間的資料互動
前端後臺互動

  1. XMLHttpRequest
    XHR
    1)傳送請求
    var request = new XMLHttpRequest();
    request.open(“GET”,”a.json”);
    request.setRequestHeader(“Content-type”,”text/plain”);
    request.send(); //null
    2)獲取響應
    status HTTP狀態碼
    200
    404
    403 跨域訪問
    500 後臺程式碼異常
    statusText HTTP狀態文字
    OK
    Not Found

    readyState      狀態碼
        0   
        1   open()
        2   伺服器接收到請求頭
        3   瀏覽器接收到響應頭
        4   響應完成
    onreadystatechange
    
    responseText    響應文字
    responseXML     Document
    
  2. <img src="/a.jpg" alt="">
    http://127.0.0.1:80/a.jpg
    

    路徑
    相對路徑
    不以/開頭,相對於當前檔案所在的目錄

    絕對路徑
        以/開頭,/代表專案的根目錄  [檔案相對於伺服器下的專案檔案]
        http://127.0.0.1:80/
        htdocs
    
  3. 封裝getTextData,getXMLData

  4. 解析了xml資料
  5. loadDom
    $.load();

    name=%E6%9D%8E%E6%98%A5%E9%9B%A8+terry&passwd=110

    name=%E6%9D%8E%E6%98%A5%E9%9B%A8+terry&passwd=110

  6. 通過ajax模擬form表單的提交
    enctype取值 application/x-www-form-urlencoded(預設)

二進位制(分段上傳) multipart/form-data (有圖片時一定要)

             text/plain;   

1)form表單怎麼提交資料
    obj={
        name :"大大大 terry",
        passwd : "123"  
    }
    編碼:
        enctype="application/x-www-form-urlencoded"
    提交時候值得樣子
        name=%E6%9D%8E%E6%98%A5%E9%9B%A8+terry&passwd=110
    編碼函式
        encodeFormData(obj){

        }
2) JSON
    obj={
        name :"大大大 terry",
        passwd : "123"  
    }
    提交時候的樣子
    {"name":"大大大 terry","passwd":"123"}

這是一個例子:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>AJAX</title>
<style>
        table{width:400px; border-collapse:collapse;}
        table td,th{border:1px solid #ccc;}
</style>
<script type="text/jscript">
    window.onload  = function(){
        var btns = document.getElementsByTagName("button");
        var tbls = document.getElementsByTagName("tbody");
            //處理資料
            function handlerData(data){

                //反序列化  將字串解析為物件
                var stus = JSON.parse(data);
                //遍歷刪除tbody中所有的子元素
                Array.prototype.slice.call(tbls[0].children,0).forEach(
                function(item){
                    tbls[0].removeChild(item);
                });

                //stus純陣列直接用forEach遍歷出陣列元素
                stus.forEach(function(stu){
                //每遍歷出一個學生建立一個tr
                //{ id,name,age,gender}  遍歷出來的是一個學生物件
                var newTr = document.createElement("tr");
                //每個學生繼續遍歷其屬性  因為每個學生當中的屬性佔一個td
                for( var key in stu){
                    //每遍歷一個屬性建立一個td
                    var  newTd = document.createElement("td");
                    //把屬性的值(內容)拿出來放入td當中
                    newTd.innerHTML = stu[key];  //屬性值 innerText
                    //把td追加到tr
                    newTr.appendChild(newTd);
                } 
                    tbls[0].appendChild(newTr);
            });
        }   
                //點選get請求按鈕,像伺服器傳送請求
                btns[0].onclick = function(){
                //ajax
                //1 例項化XMLHttpReuquest
                var  request = new XMLHttpRequest();
                //2 指定請求
                request.open("GET","data.json"); //後期-伺服器技術-"getAllstudents.action?class =1"
                //加斜槓為伺服器的根目錄 絕對路徑
                //3 設定請求頭     
                request.setRequestHeader("Content-type","text/plain;charset=UTF-8");
                //4 傳送請求頭
                request.send();

                 //處理響應
                //繫結一個on事件 監聽請求完成,然後處理資料
                request.onreadystatechange = function(){
                    console.log(request.readyState);   //2,3,4
                    if(request.readyState === 4 && request.status ===200){
                        //獲取到響應的文字資料
                        var text = request.responseText; //獲取到字串型別的json  列印在控制檯的字串
                        console.log(text);
                        handlerData(text);  //回撥
                        //var stus = JSON.parse(text);
                        //反序列化  將字串解析為物件
                        // var stus = JSON.stringify(text);
                        //console.log(stus);    


                }
        };
    };
};
</script>
</head>

<body>
    <h1>從伺服器上請求 的html檔案</h1>
    <button>get請求</button>
    <table>
        <thead>
        <tr>
            <th>學號</th>
            <th>姓名</th>
            <th>年齡</th>
            <th>性別</th>
        </tr>
    </thead>    
    <tbody>

        </tbody>
    </table>
</body>
</html>