jQuery的ajax 简单解析与实现

以下的内容只是个人的理解,技术有限,如有问题请指正(看得jq版本是1.3.2)

jQuery的ajax, 就是我看的和理解,可以用在3个方面,一个是取一个script地址并执行一些操作 $jQuery.getScript; 一个是jsonp $jQuery.getJSON;还有一个就是一般的ajax应用了我主要记录的是jsonp 和 ajax 这方面的个人理解..

jsonp

我的理解是:
创建一个全局的回调函数(假如是handler)
在创建一个<script>标签,去请求一个服务器端的地址(假如是http://www.xxx.com, 写在script标签里面就是 http://www.xxx.com?callback=handler callback是跟别人约定好的,也可以不要callback 别人主要是通过这个约定好的callback取到 函数名 handler 然后返回一个可以执行的js)
服务器端返回一个可以执行的js代码 (假如是 handler({name : "hello world"}))

一个简单的例子
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title></title> </head> <body> <input value="faqingqiu" onClick="xx()" type="button"> <script type="text/javascript"> function gg(d){ if(d.toSource){ alert(d.toSource()) }else{ alert(d.name) } } function xx(){ var head = document.getElementsByTagName("head")[0]; var script = document.createElement("script"); script.src = "http://active.zol.com.cn/guofeng/profile2.php?callback=gg"; head.appendChild(script); } </script> </body> </html>

上面的handler是 gg函数
请求的地址是 http://active.zol.com.cn/guofeng/profile2.php?callback=gg


截图为证




返回的是




页面上多了一段可以执行的script

jQuery里面 有个默认配置
 
        ajaxSettings: {
            
// url: location.href,
            global      :  true ,
            type        : 
" GET " ,
            contentType : 
" application/x-www-form-urlencoded " ,
            processData : 
true ,
            async       : 
true ,
            
/*
            timeout: 0,
            data: null,
            username: null,
            password: null,
            
*/
            
//  Create the request object; Microsoft failed to properly
             //  implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
             //  This function can be overriden by calling jQuery.ajaxSetup
            xhr: function (){
                
return  window.ActiveXObject 
                    
?   new  ActiveXObject( " Microsoft.XMLHTTP "
                    : 
new  XMLHttpRequest();
            },
            accepts: {
                xml: 
" application/xml, text/xml " ,
                html: 
" text/html " ,
                script: 
" text/javascript, application/javascript " ,
                json: 
" application/json, text/javascript " ,
                text: 
" text/plain " ,
                _default: 
" */* "
            }
        }
accepts 是设置请求头 accepts里面的配置项
 
 
type 是提交类型
async 是 是否异步 true 表示异步
processData 是否修改data的结构 如果是true 表示修改
ifModified  如果设置了这一项 就要设置http请求头里面的 If-Modified-Since 
contentType 设置请求头 contentType的类型
application/xml;
application/x-www-form-urlencoded
application/json
 
application/xml;
参数传递用<xml>

截图为证

 
 
application/x-www-form-urlencoded
 参数传递用就是一般的字符串
截图为证


application/json
 参数传递是json形式的(cnblogs就是这样的形式)
截图为证

 
 
jquery.ajax的前部分主要是对jsonp 和 创建script 的处理
jq的jsonp的用法是 callback=? 要以这种形式
所以前面部分就是判断url 是不是这中形式 不是这中形式就转成这种形式 
同时创建一个全局的变量当函数  回掉的时候执行该函数
 
ExpandedBlockStart.gif View Code
             // extend 的第一个参数为true 表示深度复制 
             // 创建一个新的对象 jq.ajaxSettings全部copy过去 把s复制过去
            s  =  jq.extend( true , s, jq.extend( true , {}, jq.ajaxSettings, s));
            
var  jsonp,
                
//  jsonp 的回调函数名字要以这种方式才行
                jsre  =   / =\?(&|$) / g,
                status,
                data,
                type 
=  s.type.toUpperCase();
                
            
// 如果data不是字符串 转成字符串
             if  ( s.data  &&    typeof  s.data  !==   " string "  )
                s.data 
=  jq.param(s.data);

            
if  ( s.dataType  ==   " jsonp "  ) {
                
if  ( type  ==   " GET "  ) {
                    
if  (  ! s.url.match(jsre) ){
                        
// get 方式 参数都在url的后面
                         // 如果没有=?这种形式 就转成这种形式  这是jq的jsonp形式  后面要把?变成函数名
                         // 转成这种形式 http://www.xxx.com?callback=?
                        s.url  +=  (s.url.match( / \? / ?   " & "  :  " ? " +  (s.jsonp  ||   " callback " +   " =? " ;                    
                    }
// http://www.baidu.com?callback=?
                }  else   if  (  ! s.data  ||   ! s.data.match(jsre) ){
                    
// post方式 有专为存放参数的地方  这里是把参数和回调都转一下 
                     // 形式 xx=xx&oo=oo.......&callback=?    
                    s.data  =  (s.data  ?  s.data  +   " & "  :  "" +  (s.jsonp  ||   " callback " +   " =? " ;
                }
                s.dataType 
=   " json " ;
            }

            
//  url 符合 定义的jsonp形式 或者 s.data符合jsonp形式
             if  ( s.dataType  ==   " json "   &&  (s.data  &&  s.data.match(jsre)  ||  s.url.match(jsre)) ) {
                
//  这里的jsonp 就是后面的可执行函数的 函数名了
                jsonp  =   " jsonp "   +  jsc ++ ;
                
                
//  Replace the =? sequence both in the query string and the data
                 //  /=\?(&|$)/g
                 // 将 ? 转 成函数名字
                 if  ( s.data )
                    s.data 
=  (s.data  +   "" ).replace(jsre,  " = "   +  jsonp  +   " $1 " );
                s.url 
=  s.url.replace(jsre,  " = "   +  jsonp  +   " $1 " );
                s.dataType 
=   " script " ;
    
                
//  定义全局的函数名了 后面请求完毕后就会执行这个函数
                window[ jsonp ]  =   function (tmp){
                    data 
=  tmp;
                    success();
                    
// complete();
                     //  Garbage collect
                    window[ jsonp ]  =  undefined;
                    
try delete  window[ jsonp ]; }  catch (e){}
                    
if  ( head )
                        head.removeChild( script );
                };
            }

            
if  ( s.dataType  ==   " script "   &&  s.cache  ==   null  )
                s.cache 
=   false ;
    
            
/* if ( s.cache === false && type == "GET" ) {
                var ts = now();
                // try replacing _= if it is there
                //alert(s.url)  http://www.baidu.com?callback=jsonp1315980993828
                var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");

                // if nothing was replaced, add timestamp to the end
                s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
            }
*/
            
//  If data is available, append data to url for get requests
             if  ( s.data  &&  type  ==   " GET "  ) {
                
// 加上其他的参数
                s.url  +=  (s.url.match( / \? / ?   " & "  :  " ? " +  s.data;
    
                
//  IE likes to send both get and post data, prevent this
                 // ie的 get post 都会传送s.data   好像就是这个意思  所以节省开支
                s.data  =   null ;
            }
            
            
//  Watch for a new set of requests
             // if ( s.global && ! jQuery.active++ )
             //     jQuery.event.trigger( "ajaxStart" );
    
            
//  Matches an absolute URL, and saves the domain
             // 取url的 前面的信息 和 域名
             var  parts  =   / ^(\w+:)?\/\/([^\/?#]+) / .exec( s.url );
            
            
if  ( s.dataType  ==   " script "   &&  type  ==   " GET "   &&  parts
            
&&  ( parts[ 1 &&  parts[ 1 !=  location.protocol  ||  parts[ 2 !=  location.host )){
                
var  head  =  document.getElementsByTagName( " head " )[ 0 ];
                
var  script  =  document.createElement( " script " );
                script.src 
=  s.url;
                
if  (s.scriptCharset)
                    script.charset 
=  s.scriptCharset;
    
                
// 如果不是jsonp方式  就是创建一个script标签
                 if  (  ! jsonp ) {
                    
// 保证回调函数只执行一次
                     var  done  =   false ;
    
                    
//  Attach handlers for all browsers  兼容所有的浏览器的写法
                    script.onload  =  script.onreadystatechange  =   function (){
                        
if  (  ! done  &&  ( ! this .readyState  ||
                                
this .readyState  ==   " loaded "   ||   this .readyState  ==   " complete " ) ) {
                            done 
=   true ;
                            
// success();
                             // complete();

                            
//  Handle memory leak in IE  jq里面可以说反复的强调了 删除元素时 该dom元素引用的对象要断开引用  不然会内存泄露
                            script.onload  =  script.onreadystatechange  =   null ;
                            head.removeChild( script );
                        }
                    };
                }    
                head.appendChild(script);    
                
//  We handle everything using the script element injection
                 return  undefined;
            }
 
 
jQuery.ajax 的后面的部分就是处理ajax的了
jq有专门的设置请求头的部分
其中的   If-Modified-Since 比较重要了
jq里面用 jquery.lastModified 来保存最后的修改时间的
形式是 jquery.lastModified[url] = 时间
按我的理解是 
我发送一次请求后  服务器看在 If-Modified-Since  里面的时间后有没有做修改,没有做修改返回304 读缓存的文件 有做修改返回200
这么做的好处是可以节约网络资源咯
 
jq1.3.2里面是设置的定时器 去判断请求是否已经完成
onreadystatechange是定时器去执行的函数
如果设置了s.timeout
会在这个时间后去查看是否已经xhr的状态  是否已经完成了回调  如果没有 abort 终止掉请求
 
jq还有一些方法配合 ajajx
jquery.httpSuccess
jquery.httpNotModified
jquery.httpData
 
jquery.httpSuccess
判断请求是否已经成功了
jquery.httpNotModified
判断 服务器那边是否已经做过了修改
jquery.httpData
因为返回的数据是根据请求头的content-type来的,所以要对不同的数据做处理
因为返回的数据是根据请求头的content-type来的,所以要对不同的数据做处理
在这里 又对 xml script  json 的处理
其中script 用到了jquery.globalEval
 
一个完整的例子
<!DOCTYPE html > <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title></title> </head> <body> <script type="text/javascript"> (function(undefined){ var win = this, toString = Object.prototype.toString; function now(){ return +new Date; } var jsc = now(); win.jq = { isFunction : function(obj){ return toString.call(obj) === "[object Function]"; }, isArray : function(obj){ return toString.call(obj) === "[object Array]"; }, each : function(object, callback, args){ var name, i = 0, length = object.length; if ( args ) { if ( length === undefined ) { for ( name in object ) if ( callback.apply( object[ name ], args ) === false ) break; } else for ( ; i < length; ) if ( callback.apply( object[ i++ ], args ) === false ) break; } else { if ( length === undefined ) { for ( name in object ) if ( callback.call( object[ name ], name, object[ name ] ) === false ) break; } else for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} } return object; }, extend : function(){ var target = arguments[0] || {}, i = 1, length = arguments.length, deep = true, options; if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; i = 2; } if ( typeof target !== "object" && Object.prototype.toString.call(target)!="[object Function]") target = {}; for(;i<length;i++){ if ( (options = arguments[ i ]) != null ) for(var name in options){ var src = target[ name ], copy = options[ name ]; if ( target === copy ) continue; if ( deep && copy && typeof copy === "object" && !copy.nodeType ){ target[ name ] = arguments.callee( deep, src || ( copy.length != null ? [ ] : { } ), copy ); } else if(copy !== undefined) target[ name ] = copy; } } return target; }, param : function(a){ var s = []; function add(key,value){ s[s.length] = encodeURIComponent(key) + '=' + encodeURIComponent(value); }; if(jq.isArray(a)){ jq.each(a,function(){ add(this.name,this.value); }); }else{ for(var j in a){ if(jq.isArray(a[j])) jq.each(a,function(){ add(this.name,this.value); }); else add( j , jq.isFunction(a[j]) ? a[j]() : a[j] ); } }; return s.join("&").replace(/%20/g, "+"); }, // Determines if an XMLHttpRequest was successful or not httpSuccess: function( xhr ) { try { // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450 return !xhr.status && location.protocol == "file:" || ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223; } catch(e){} return false; }, // Determines if an XMLHttpRequest returns NotModified httpNotModified: function( xhr, url ) { //判断 服务器那边是否已经做过了修改 try { var xhrRes = xhr.getResponseHeader("Last-Modified"); // Firefox always returns 200. check Last-Modified date // 好像 firefox无视是否修改吗 没测试过 return xhr.status == 304 || xhrRes == jq.lastModified[url]; } catch(e){} return false; }, httpData: function( xhr, type, s ) { var ct = xhr.getResponseHeader("content-type"), xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0, //判断返回的是xml还是字符串 data = xml ? xhr.responseXML : xhr.responseText; if ( xml && data.documentElement.tagName == "parsererror" ) throw "parsererror"; // Allow a pre-filtering function to sanitize the response // s != null is checked to keep backwards compatibility //if( s && s.dataFilter ) // data = s.dataFilter( data, type ); // The filter can actually parse the response if( typeof data === "string" ){ // If the type is "script", eval it in global context //如果类型是script 则创建一个标签 并且执行data里面的内容 if ( type == "script" ) jq.globalEval( data ); // Get the JavaScript object, if JSON is used. if ( type == "json" ) data = window["eval"]("(" + data + ")"); } return data; }, handleError : function(){ }, // Evalulates a script in a global context globalEval: function( data ) { if ( data && /\S/.test(data) ) { // Inspired by code by Andrea Giammarchi // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html var head = document.getElementsByTagName("head")[0] || document.documentElement, script = document.createElement("script"); script.type = "text/javascript"; //if ( jQuery.support.scriptEval ) //script.appendChild( document.createTextNode( data ) ); //else script.text = data; // Use insertBefore instead of appendChild to circumvent an IE6 bug. // This arises when a base node is used (#2709). head.insertBefore( script, head.firstChild ); head.removeChild( script ); } }, get: function( url, data, callback, type ) { // shift arguments if data argument was ommited if ( jq.isFunction( data ) ) { callback = data; data = null; } return jq.ajax({ type : "GET", url : url, data : data, success : callback, dataType : type }); }, getScript: function( url, callback ) { return jq.get(url, null, callback, "script"); }, getJSON: function( url, data, callback ) { return jq.get(url, data, callback, "json"); }, ajaxSettings: { //url: location.href, global : true, type : "GET", contentType : "application/x-www-form-urlencoded", processData : true, async : true, /* timeout: 0, data: null, username: null, password: null, */ // Create the request object; Microsoft failed to properly // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available // This function can be overriden by calling jQuery.ajaxSetup xhr:function(){ return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest(); }, accepts: { xml: "application/xml, text/xml", html: "text/html", script: "text/javascript, application/javascript", json: "application/json, text/javascript", text: "text/plain", _default: "*/*" } }, lastModified : {}, ajax : function(s){ //extend 的第一个参数为true 表示深度复制 //创建一个新的对象 jq.ajaxSettings全部copy过去 把s复制过去 s = jq.extend(true, s, jq.extend(true, {}, jq.ajaxSettings, s)); var jsonp, // jsonp 的回调函数名字要以这种方式才行 jsre = /=\?(&|$)/g, status, data, type = s.type.toUpperCase(); //如果data不是字符串 转成字符串 if ( s.data && s.processData&&typeof s.data !== "string" ) s.data = jq.param(s.data); if ( s.dataType == "jsonp" ) { if ( type == "GET" ) { if ( !s.url.match(jsre) ){ //get 方式 参数都在url的后面 //如果没有=?这种形式 就转成这种形式 这是jq的jsonp形式 后面要把?变成函数名 //转成这种形式 http://www.xxx.com?callback=? s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?"; }//http://www.baidu.com?callback=? } else if ( !s.data || !s.data.match(jsre) ){ //post方式 有专为存放参数的地方 这里是把参数和回调都转一下 //形式 xx=xx&oo=oo.......&callback=? s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?"; } s.dataType = "json"; } // url 符合 定义的jsonp形式 或者 s.data符合jsonp形式 if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) { // 这里的jsonp 就是后面的可执行函数的 函数名了 jsonp = "jsonp" + jsc++; // Replace the =? sequence both in the query string and the data // /=\?(&|$)/g //将 ? 转 成函数名字 if ( s.data ) s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1"); s.url = s.url.replace(jsre, "=" + jsonp + "$1"); s.dataType = "script"; // 定义全局的函数名了 后面请求完毕后就会执行这个函数 window[ jsonp ] = function(tmp){ data = tmp; success(); //complete(); // Garbage collect window[ jsonp ] = undefined; try{ delete window[ jsonp ]; } catch(e){} if ( head ) head.removeChild( script ); }; } if ( s.dataType == "script" && s.cache == null ) s.cache = false; /*if ( s.cache === false && type == "GET" ) { var ts = now(); // try replacing _= if it is there //alert(s.url) http://www.baidu.com?callback=jsonp1315980993828 var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2"); // if nothing was replaced, add timestamp to the end s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : ""); }*/ // If data is available, append data to url for get requests if ( s.data && type == "GET" ) { //加上其他的参数 s.url += (s.url.match(/\?/) ? "&" : "?") + s.data; // IE likes to send both get and post data, prevent this //ie的 get post 都会传送s.data 好像就是这个意思 所以节省开支 s.data = null; } // Watch for a new set of requests //if ( s.global && ! jQuery.active++ ) // jQuery.event.trigger( "ajaxStart" ); // Matches an absolute URL, and saves the domain //取url的 前面的信息 和 域名 var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url ); if ( s.dataType == "script" && type == "GET" && parts && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){ var head = document.getElementsByTagName("head")[0]; var script = document.createElement("script"); script.src = s.url; if (s.scriptCharset) script.charset = s.scriptCharset; //如果不是jsonp方式 就是创建一个script标签 if ( !jsonp ) { //保证回调函数只执行一次 var done = false; // Attach handlers for all browsers 兼容所有的浏览器的写法 script.onload = script.onreadystatechange = function(){ if ( !done && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") ) { done = true; //success(); //complete(); // Handle memory leak in IE jq里面可以说反复的强调了 删除元素时 该dom元素引用的对象要断开引用 不然会内存泄露 script.onload = script.onreadystatechange = null; head.removeChild( script ); } }; } head.appendChild(script); // We handle everything using the script element injection return undefined; } //用一个保证回掉函数只执行一次 var requestDone = false; var xhr = s.xhr(); // Open the socket // Passing null username, generates a login popup on Opera (#2865) if( s.username ) xhr.open(type, s.url, s.async, s.username, s.password); else xhr.open(type, s.url, s.async); try { if ( s.data ) xhr.setRequestHeader("Content-Type", s.contentType); // Set the If-Modified-Since header, if ifModified mode. //If-Modified-Since 记录页面最后修改时间的 HTTP 头信息 // 会和服务器的时间比较 在这个时间内 返回的是304 if ( s.ifModified ) xhr.setRequestHeader("If-Modified-Since", jq.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" ); // Set header so the called script knows that it's an XMLHttpRequest xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); // Set the Accepts header for the server, depending on the dataType xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ? s.accepts[ s.dataType ] + ", */*" : s.accepts._default ); } catch(e){} //发送钱的回调 如果回调函数的返回是false abort掉 if ( s.beforeSend && s.beforeSend(xhr, s) === false ) { xhr.abort(); return false; } var onreadystatechange = function(isTimeout){ // The request was aborted, clear the interval and decrement jQuery.active if (xhr.readyState == 0) { if (ival) { // clear poll interval clearInterval(ival); ival = null; } // The transfer is complete and the data is available, or the request timed out } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) { //保证回调只执行一次 requestDone = true; //清空掉定时器 if (ival) { clearInterval(ival); ival = null; } status = isTimeout == "timeout" ? "timeout" : !jq.httpSuccess( xhr ) ? "error" : s.ifModified && jq.httpNotModified( xhr, s.url ) ? "notmodified" : "success"; //判断是否已经超时 if ( status == "success" ) { // Watch for, and catch, XML document parse errors try { // process the data (runs the xml through httpData regardless of callback) data = jq.httpData( xhr, s.dataType, s ); } catch(e) { status = "parsererror"; } } // Make sure that the request was successful or notmodified if ( status == "success" ) { // Cache Last-Modified header, if ifModified mode. var modRes; try { modRes = xhr.getResponseHeader("Last-Modified"); } catch(e) {} // swallow exception thrown by FF if header is not available //记录下最后请求的时间 因为之后再请求的话 还要继续和服务器的时间比较 if ( s.ifModified && modRes ) jq.lastModified[s.url] = modRes; // JSONP handles its own success callback if ( !jsonp ) success(); } else jq.handleError(s, xhr, status); // Fire the complete handlers complete(); if ( isTimeout ) xhr.abort(); // Stop memory leaks if ( s.async ) xhr = null; } }; if ( s.async ) { // don't attach the handler to the request, just poll it instead var ival = setInterval(onreadystatechange, 13); // Timeout checker if ( s.timeout > 0 ) setTimeout(function(){ // Check to see if the request is still happening if ( xhr && !requestDone ) onreadystatechange( "timeout" ); }, s.timeout); } xhr.send(s.data); function success(){ // If a local callback was specified, fire it and pass it the data if ( s.success ) s.success( data, status ); } function complete(){ // Process result if ( s.complete ) s.complete(xhr, status); } }, xx :'1' } })(); window.onload = function(){ } </script> </body> <input value="jsonp" type="button" onClick="d1()"><br/><br/><br/> <input value="一般的请求" type="button" onClick="d2()"><br/><br/><br/> 本想弄个If-Modified-Sinc的例子 但是发现cnblogs的xhr的请求的响应头 全部都没有Last-Modifie <script type="text/javascript"> function t(data){ 'toSource' in data ? alert(data.toSource()) : alert(data.name) } function d1(){ jq.getJSON("http://active.zol.com.cn/guofeng/profile2.php?callback=?", t); } function d2(){ jq.ajax({ type : 'post', ifModified : true, dataType : 'json', processData : false, contentType : 'application/json', data : '{"postId":2169079,"blogId":56660,"dateCreated":"2011/9/6 18:54:00"}', url : "http://www.cnblogs.com/ws/BlogDetailWs.asmx/GetPrevNext", success : function(data){ if('toSource' in data){ alert(data.toSource()) }else{ for(var name in data){ alert(name+':'+data[name]) } } } }); } function d3(){ jq.ajax({ type : 'post', ifModified : true, dataType : 'json', ifModified : true, processData : false, contentType : 'application/json', data : '{"postId":2169079,"blogId":56660,"dateCreated":"2011/9/6 18:54:00"}', url : "http://www.cnblogs.com/ws/BlogDetailWs.asmx/GetPrevNext", success : function(data){ if('toSource' in data){ alert(data.toSource()) }else{ for(var name in data){ alert(name+':'+data[name]) } } } }); } </script> </html>

转载于:https://www.cnblogs.com/wtcsy/archive/2011/09/15/2177770.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值