jQuery实现jsonp源码分析,京东2015面试

// Bind script tag hack transport

jQuery.ajaxTransport( "script", function(s) {

// This transport only deals with cross domain requests

  if ( s.crossDomain ) {

    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 );

        }

      }

    };

  }

});

var oldCallbacks = [],

rjsonp = /(=)\?(?=&|$)|\?\?/;

// Default jsonp settings

jQuery.ajaxSetup({

  jsonp: "callback",

  jsonpCallback: function() {

    var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );

    this[ callback ] = true;

    return callback;

  }

});

jsonp的实现与原理:

$.ajax({

url: 'http://192.168.1.114/yii/demos/test.php', //不同的域

type: 'GET',    // jsonp模式只有GET是合法的

data: {

'action': 'aaron'

},          // 预传参的数组

dataType: 'jsonp', // 数据类型

jsonp: 'backfunc', // 指定回调函数名,与服务器端接收的一致,并回传回来

})

其实jquery内部会转化成

http://192.168.1.114/yii/demos/test.php?backfunc=jQuery2030038573939353227615_1402643146875&action=aaron;

然后动态加载

<script type="text/javascript" src="http://192.168.1.114/yii/demos/test.php?backfunc=jQuery2030038573939353227615_1402643146875&action=aaron"></script>

问题:backfunc=jQuery2030038573939353227615_1402643146875是怎么产生的?

  jsonpCallback: function() {

    var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );

  }

  expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" );

  ajax_nonce = jQuery.now();

//如果没有设置jsonpCallback的话就把callback的名字(jsonpCallback)随机设置为jQuery+版本号+随机数+_$.now()现在的时间