这几天在看面试题,发现跨域这个知识点被问到很多次,网上搜了搜各种资料,五花八门,- - …整了半天,算是明白了什么意思。总结如下:
首先要明白的是:<
script>
标签是不受同源策略的限制的,它可以载入任意地方的 JavaScript 文件,而并不要求同源。同样的有src属性的标签都不受同源策略的限制,比如<img><iframe>
.跨域的核心就是利用这个。
JSONP 的理念就是,我和服务端约定好一个函数名,当我请求文件的时候,服务端返回一段 JavaScript。这段 JavaScript 调用了我们约定好的函数,并且将数据当做参数传入.
先看个简单的:
需要获取数据的页面:index.html
<script>
function getWeather(data) {
console.log(data);
}
</script>
<script src="http://x.y.com/xx.js">
http://x.y.com/xx.js 文件内容:
getWeather({
"城市": "北京",
"天气": "大雾"
});
我们可以看到,在我们定义了 getWeather(data) 这个函数后,直接载入了 xx.js。在这个脚本中,执行了 getWeather 函数,并传入了一个对象,并将这个对象输出到 console 中。
这就是整个 JSONP 的流程。
以上过程没有涉及到跟服务器的交互,下面看一下这个代码。
<script src="http://jd.com/data.php?callback=dosomething"></script>
<script type="text/javascript">
function dosomething(jsondata){
console.log(jsondata);//打印获得的json数据
}
</script>
按我自己的理解,第一个<
script>
是载入http://jd.com/data.php,并且向data.php传入了一个回调函数名,也就是something,
data.php
<?php
$callback = $_GET['callback'];//得到回调函数名,
$data = {'name':'张三',sex:'男',age:'15'};//要返回的数据
echo$callback.'('.json_encode($data).')';//输出
?>
上面的data.php运行执行完毕后,输出dosomething({‘name’:’张三’,sex:’男’,age:’15’});,仔细看看这是什么。这不就是执行函数dosomething,参数是{‘name’:’张三’,sex:’男’,age:’15’},
函数执行完毕后,最后的输出结果是:
第二个与服务器交互的JSONP和第一个不与服务器交互的JSONP其实是一样的道理,只不过是第一个JSONP中第二个载入的<script>
已经写好了要执行的函数,并且指定了参数。第二个JSONP的第二个<script>
需要在后台拼接好带参执行函数的样子,然后执行。这时候,后台人员有必要知道前台要执行的函数的名字和参数。所以第二个JSONP的第一个<script>
声明了函数。
以上是原生函数的jsonp跨域过程。
看下用jQuery怎么写:
<script type="text/javascript" src=jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
$.ajax({
type: "get",
async: false,
url: "http://jd.com/data.php",
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"dosomething",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function {
console.log(jsondata);//打印获得的json数据
};
},
error: function(){
alert('fail');
}
});
});
</script>
还有些别的封装方法:
$.getJSON("http://jd.com/data.php?callback=?", function(data) {
console.log(data);
});
// 2
$.get('http://jd.com/data.php', function(data) {
console.log(data);
}, 'jsonp');
需要注意的是getJSON方法的请求地址url需要带上callback=?,因为jq对该方法进行封装的时候并没有默认回调函数变量名为callback,于是php中$_GET[‘callback’]就找不到变量值了。
而一般的jq方法url 中不用指定 callback 参数。对于 jQuery 中的 jsonp 来说,callback 参数是自动添加的。默认情况下,jQuery 生成的 jsonp 请求中 callback 参数是形如 callback=jQuery200023559735575690866_1434954892929 这种根据看似随机的名字,对应的就是 success 那个处理函数,所以一般不用特意处理。
最后来总结下JSONP的跨域:
关键点:浏览器对XHR做了同源策略,但并没有将这种方式延续到script上,从而可以利用动态script标签技术来做到跨域请求的作用。
兼容性:所有浏览器都兼容这种方式;
优点:很明显前端可以很轻松的做到跨域请求;
缺点
只能通过GET方式请求,一方面是参数长度有限制,二是安全性比较差;
**后端需要知道前端的回调函数是什么样的结构,主要在参数和回调名;
后端需要进行参数和回调函数名的拼接然后才能执行;**