什么是跨域:
浏览器同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)。
与一个不满足同源策略的域的页面进行交互,就是跨域。
跨域三种方案:
1. ifram标签
html中有一些标签不受同源策略限制,ifram就是其中一个。
2. postMessage
属于h5新增api。
3. JSONP
最常用的就是JSONP,也是面试中最常考的。JSONP简单来说就是动态生成js脚本。这里需要服务端配合,调用者可以传一个参数过去告诉服务端 “我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成js脚本并响应了。
示例代码:
    var flightHandler = function(data){
        alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
    };
    // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
    var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
    // 创建script标签,设置其属性
    var script = document.createElement('script');
    script.setAttribute('src', url);
    // 把script标签加入head,此时调用开始
    document.getElementsByTagName('head')[0].appendChild(script); 
最终服务器端生成的返回给请求页面的代码段应该是这样的:
flightHandler({
    "code": "CA1998",
    "price": 1780,
    "tickets": 5
});
jsonp乍看给ajax很像,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装。
jquery实现jsonp:
    jQuery(document).ready(function(){ 
        $.ajax({
             type: "get",
             async: false,
             url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
             dataType: "jsonp",
             jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
             jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
             success: function(json){
                 alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
             },
             error: function(){
                 alert('fail');
             }
         });
     });
但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加。
JSONP常考面试题:
手写jsonp:
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[cbval] = function(data) {
        //这里执行回调的操作,用回调来处理参数
      callback(data);
      //拿到了就删掉这个script
      document.body.removeChild(script);
    };
    document.body.appendChild(script);
}
jsonp(
    "https://www.baidu.com",
    {aa:11},
    function(){
        console.log(param);
    }
);














网友评论