$.ajax其實底層還是用的XMLHttpRequest,對於加載數據的格式datatype有:xml、text、html、json、jsonp、script。
其中xml、text不需要處理,直接使用原生的responseXML、responseText。對於html、json其實也是用responseText接收的,對於json格式,jquery拿到responseText后會預先用JSON.parse()去格式化一下json數據再傳給回調函數。
對於jsonp和script的,其實不走xhr對象,直接使用script標簽。但是在使用datatype=script之前,jquery還是做了判斷,只有跨域請求才會走<script>標簽。
具體判斷如下:
s.crossDomain = !!( parts && ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !== ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) ) );
此處代碼會判斷(請求的url===location.href)。如果不等於,相當於跨域,jquery會主動判斷為跨域請求,使用script標簽進行處理。如下代碼:
jQuery.ajaxTransport( "script", function( s ) { // This transport only deals with cross domain requests if ( s.crossDomain ) {//jquery判斷是否跨域,跨域才會添加script標簽 var script, head = document.head || jQuery( "head" )[ 0 ] || document.documentElement; return { send: function( _, callback ) { script = document.createElement( "script" ); script.async = true; if ( s.scriptCharset ) { script.charset = s.scriptCharset; } script.src = s.url; // Attach handlers for all browsers script.onload = script.onreadystatechange = function( _, isAbort ) { if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) { // Handle memory leak in IE script.onload = script.onreadystatechange = null; // Remove the script if ( script.parentNode ) { script.parentNode.removeChild( script ); } // Dereference the script script = null; // Callback if not abort if ( !isAbort ) { callback( 200, "success" ); } } }; // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending // Use native DOM manipulation to avoid our domManip AJAX trickery head.insertBefore( script, head.firstChild ); }, abort: function() { if ( script ) { script.onload( undefined, true ); } } }; } } );
同時在請求之前,jquery還做了一些事情。
header里寫了:
X-Requested-With = "XMLHttpRequest";
If-Modified-Since = url;
Content-Type = application/x-www-form-urlencoded; 這個是讓ajax提交模擬form表單提交的數據,從瀏覽器端看到的是如下:

