var xhr=new XMLHttpRequest();xhr.onreadystatechange=function(e){ console.log(e); if(xhr.readyState==4 && xhr.status==200){ console.log(xhr); console.log(xhr.responseText); }}xhr.open('get','./data.json');xhr.send();
response中已經有了數據,響應內容默認爲字符串
responseType爲'',也就是默認值
responseText中是響應主體的內容
responseURL指出了咱們請求的資源路徑javascript
上圖中的信息:responseType是一個空字符串,也就是指明瞭返回的是一個字符串,並且從下面的log咱們也能夠看出來,爲了清楚,我把xhr.responseText的類型也打印了出來,確實是string。
而若是咱們換成下面的代碼:html
var xhr=$.ajax({ url:'./data.json', success:function(data){ console.log(data); } }); console.log(xhr);
獲得結果截圖以下:
這個被jQuery改的面目全非的xmlhttprequest對象,先看一個左側的屬性,其中有一個responseJSON,這是jquery的實現,標準中是沒有這個屬性的,而它的responseText是字符串。因此success回調應該就是調的這個屬性咯。看下請求,沒有什麼區別:Content-Type都是application/json ,其實咱們再切到response標籤看下,是同樣的數據格式。因此是否是能夠說原生獲取json格式數據的話,值都是json字符串形式的值?前端
這裏的jquery版本爲1.11.2,查看源碼能夠發現:在ajax方法中定義的done方法內,有這麼一句:java
// Get response data 這裏是獲得相應的內容,本例就是"'{"username":"ruby","age":"18"}'"if ( responses ) { response = ajaxHandleResponses( s, jqXHR, responses );}// Convert no matter what (that way responseXXX fields are always set)response = ajaxConvert( s, response, jqXHR, isSuccess );
也就是說,在獲得最終請求數據時,jquery會去作響應內容的自動轉換,先來看ajaxHandleResponses方法,它用於返回響應內容:jquery
function ajaxHandleResponses(s, jqXHR, responses) { var firstDataType, ct, finalDataType, type, contents = s.contents, dataTypes = s.dataTypes; // Remove auto dataType and get content-type in the process while (dataTypes[0] === "*") { dataTypes.shift(); if (ct === undefined) { ct = s.mimeType || jqXHR.getResponseHeader("Content-Type"); /*這裏的s是使用ajax傳入的參數轉化而來的對象,用於存儲前端開發人員發起該請求時對請求的一些設置和js默認對請求的設置,s.mimeType是使用overrideMIMEType時會被寫入s的,其實也就是在ajax方法中咱們指定的contentType,若是沒有該屬性,就是查找相應對象的Content-Type屬性,而這個是確定有值的,本例中ct='application/json',即獲取到了響應報文中報頭Content-Type的值*/ } } // Check if we're dealing with a known content-type if (ct) { for (type in contents) { /* contents是一個固定的對象,用於匹配各類類型的數據 { html: /html/ json: /json/ script: /(?:java|ecma)script/ xml: /xml/ } */ if (contents[type] && contents[type].test(ct)) { dataTypes.unshift(type); /* 這裏咱們顯然是匹配到了json這一項,因此dataTypes中加上一項['json'] */ break; } } } // Check to see if we have a response for the expected dataType if (dataTypes[0] in responses) { finalDataType = dataTypes[0]; /* 若是這個類型的數據在responses中正好有,那麼就直接將最終類型定義爲dataType中的這一項,本例中,dataTypes[0]爲'json',但實際返回的響應是text。responses就是根據相應內容生成的響應對象,這裏是"{text:"{"username":"ruby","age":"18"}"}". */ } else { // Try convertible dataTypes for (type in responses) { if (!dataTypes[0] || s.converters[type + " " + dataTypes[0]]) { /* 檢測responses中的各個類型的值是否能夠轉換爲咱們想獲得的類型, 本例中這裏的type爲'text',s.converters定義的是各類轉換用到的函數,好比s.converters['text json']=JSON.parse。本例中這裏是能夠轉換的。列出來吧: s.converters:{ "text script": function( text ) { jQuery.globalEval( text ); return text; }, // Convert anything to text "* text": String, // Text to html (true = no transformation) "text html": true, // Evaluate text as a json expression "text json": jQuery.parseJSON, // Parse text as xml "text xml": jQuery.parseXML } */ finalDataType = type; break; } if (!firstDataType) { firstDataType = type; } } // Or just use first one finalDataType = finalDataType || firstDataType; } // If we found a dataType // We add the dataType to the list if needed // and return the corresponding response if (finalDataType) { if (finalDataType !== dataTypes[0]) { dataTypes.unshift(finalDataType); //完善s.dataTypes中的值,即完善響應數據的類型,此時爲['text','json'] } return responses[finalDataType]; //最終返回responses['text'] }}
再來看ajaxConvert方法: ajax
/* Chain conversions given the request and the original response* Also sets the responseXXX fields on the jqXHR instance*/function ajaxConvert(s, response, jqXHR, isSuccess) { var conv2, current, conv, tmp, prev, converters = {}, // Work with a copy of dataTypes in case we need to modify it for conversion dataTypes = s.dataTypes.slice(); //數組copy這麼寫?不知道爲啥~你知道的話還望不吝賜教~ // Create converters map with lowercased keys if (dataTypes[1]) { for (conv in s.converters) { converters[conv.toLowerCase()] = s.converters[conv]; //構造一個轉換對象,內容是s.converters中的那些轉換函數. } } current = dataTypes.shift(); // Convert to each sequential dataType while (current) { if (s.responseFields[current]) { jqXHR[s.responseFields[current]] = response; /* 這裏給jqXHR即jquery構造出來的XMLHttpRequest對象賦值,在本例中,它在此添加了兩個屬性,一個是responseText,一個是responseJson */ } // Apply the dataFilter if provided if (!prev && isSuccess && s.dataFilter) { response = s.dataFilter(response, s.dataType); } prev = current; current = dataTypes.shift(); //記住第一個類型,再獲取第二個類型,這裏的prev爲‘text’, current爲'json'。 if (current) { // There's only work to do if current dataType is non-auto if (current === "*") { current = prev; // Convert response if prev dataType is non-auto and differs from current } else if (prev !== "*" && prev !== current) { // Seek a direct converter conv = converters[prev + " " + current] || converters["* " + current]; //看看是否有prev類轉current類的轉換方法 // If none found, seek a pair if (!conv) { for (conv2 in converters) { // If conv2 outputs current tmp = conv2.split(" "); if (tmp[1] === current) { // If prev can be converted to accepted input conv = converters[prev + " " + tmp[0]] || converters["* " + tmp[0]]; if (conv) { // Condense equivalence converters if (conv === true) { conv = converters[conv2]; // Otherwise, insert the intermediate dataType } else if (converters[conv2] !== true) { current = tmp[0]; dataTypes.unshift(tmp[1]); } break; } } } } // Apply converter (if not an equivalence) if (conv !== true) { // Unless errors are allowed to bubble, catch and return them if (conv && s["throws"]) { response = conv(response); } else { try { response = conv(response); //轉換爲咱們想要的數據類型,截至此咱們已經獲得想要的json數據啦 } catch (e) { return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; } } } } } } return {state: "success", data: response};}
上面基本根據當前案例進行代碼解析,不少狀況沒有一一列出,感興趣的童鞋能夠經過打斷點調試的方式來解析代碼。express