手写个jsonp


原生jsonp具体实现

先上代码:

    //http://www.baidu.com?aa=11&callback=my_jsonp04349289664328899
    var jsonp = function(url,param,callback){
        //处理url地址,查找?,如果没有?这个变量就有一个"?",有?这个变量接收一个&
        var querystring = url.indexOf("?") == -1?"?":"&";

        //处理参数{xx:xx}
        for(var k in param) {
            querystring += k + "=" + param[k] + '&';//?k=para[k]
        }

        //处理回调函数名
        var random = Math.random().toString().replace(".","");
        var cbval = "my_jsonp" + random;
        var cb = "callback="+cbval;

        querystring += cb;

        var script = document.createElement("script");
        script.src = url + querystring;

        //把回调函数的名字附给window
        window[cbval] = function(param) {
            //这里执行回调的操作,用回调来处理参数
          callback(param);
          //拿到了就删掉这个script
          document.body.removeChild(script);
        };
        document.body.appendChild(script);
    }

    jsonp(
        "https://www.baidu.com",
        {aa:11},
        function(){
            console.log(param);
        }
        );

思路:

  1. 先抽象需要处理的字符串

  2. 处理完url,创建一个新的script标签挂到页面上

  3. 把处理好的回调函数挂到window对象上

  4. 回调完再删掉script

步骤:

随便拿个地址,比如百度。

  • http://www.baidu.com?aa=11&callback=my_jsonp04349289664328899

  • 要处理的就是地址(?及之前的内容)

  • 参数(?后面的内容)

  • 回调函数

var jsonp = function(url,para,callback){}
//地址、参数、回调

开始处理url地址

  • 域名是我们自己传进去的,所以只要处理?之后的内容就好了

var queryString = url.indexOf("?") == -1?"?":"&";
//看url里面有没有?,如果有说明只要传参数就好了,没有的话queryString默认是?

//给地址传参数一般都是要好几个,所以这里的数据格式是一个对象,如{aa:11}
for(var k in para) {
  queryString += k + '=' + para[k] + '&';
  //?aa=11&
}

处理回调函数

  • 仿jQ的思路,函数名随机,避免和页面的某个函数重名

  • 需要一个随机非浮点数

  • 参数名

var random = Math.random().toString().replace(".","");//随机非浮点数
var cbvalue = "jp" + random;//不能用数字开头做函数名
var cb = "callback=" + cbvalue;//callback = jp016548432158485
queryString += cb;//放到处理url字符串的后面

创建一个script

var script = document.createElement("script");
script.src = queryString;
document.body.appendChild(script);

把回调函数挂载到页面上,并传参

window[cbvalue] = function(para){
  callback(para);
  //拿完了参数就删掉,过河拆桥
  document.body.removeChild(script);
}

完成,尝试调用

jsonp("www.jd.com",{num:10},function(){
  console.log(para);
})