一言以蔽之,json返回的是一串数据;而jsonp返回的是脚本代码(包含一个函数调用);javascript
JSON其实就是JavaScript中的一个对象,跟var obj={}在质上彻底同样,只是在量上能够无限扩展。简单地讲,json其实就是JavaScript中的对象(Object)和数组(Array,其实也是对象)这倆好基友在那儿你嵌我我嵌你地套上n多层,以此模拟出许多复杂的数据结构。php
json易于人阅读和编写,也易于机器解析和生成,相对网络传输速率较高,功能型网站先后端每每要频繁大量交换数据,而json凭借其强大的表现力和高颜值渐渐地成为理想的先后端数据交换语言。那xml前辈呢,我以为应该会像微软的xp那样功成身退。html
同源(不懂同源策略的童鞋请自行百度)下的先后端数据交换格式肯定使用json了,那么问题来了,若是我想获取别人网站上提供的数据肿么作到呢?也就是跨域读取数据问题(不要钻牛角说你不须要读取其余网站的数据,相信我,你迟早得须要),json行不行呢?答案是No Way,为何呢,由于json只是普通的文本格式,能让你这样就轻松拿到那服务端就没有任何安全和保密性可言了,这样的话互联网世界非乱套不可,这个问题那些牛X的规范制定者早就想到了,因此使用了同源策略来限制文件获取。最后的结果就是只有像img、script、iframe这类能够指定src属性的标签有跨域获取别人网站上数据(图片,脚本,源文件其实都是数据)的能力。好比:java
<!--京东商品图片--> <img src="http://img30.360buyimg.com/jgsq-productsoa/jfs/t2407/323/1635505465/47386/f2d89d88/56615e00N7a475ee6.jpg" /> <!--百度CDN--> <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
看来直接获取json是行不通了,那有没有其余方法能拿到数据呢?因而乎jsonp就这样被聪明的开发者给发现了,为何说是发现而不是发明呢,由于并无涉及到任何新技术,就像发现ajax同样。jquery
jsonp原理是这样的,网站A须要获取网站B的数据,网站B说我给大家一个方法,【1. 大家使用<script src="http://www.B.com/open.js"></script>标签先获取到open.js文件(网站B的责任),这里边有大家须要的数据。2. 大家获取数据后处理数据(总得处理数据吧)的方法名必须命名为foo(数据请求者的责任和义务)】,这里至关于B网站和请求获取数据者之间创建了一个协议,要求请求者务必按照规则办事,若是请求者不能同时遵照上面两条就不能按预期获取数据。额..,这也算至关于创建了一个潜规则吧ajax
open.js内容json
foo({"name":"B","age":23}); //为何不直接写成json数据{"name":"B","age":23}呢,缘由很简单,在js文件总得合乎js语法吧 //这也是为何协议中明确规定处理数据的方法名必须命名为foo,由于B网站是在假定请求者的脚本中已经定义了数据处理方法foo的状况下返回数据; //否则就会报foo is not defined错误
网站A脚本须有后端
function foo(data){ console.log(data); //ToDo.. }
啊!虽然拐了个弯,但数据总算获得了,网站A,网站B都很是高兴,那么问题又来了,网站C说也须要获取网站B的数据,网站B把协议甩给它,网站C拿过来一看,草泥马啊,foo这个名字已经在本身的脚本文件的6868行用过了,并且已经使用在脚本的各个角落,批量替换会致使不少潜在bug啊,网站B情急之下决定把foo改为fool,网站A立马蹦起来,由于本身的网站已经在不少地方使用foo引用了数据。跨域
为了不上面状况发生,那些牛X哄哄的开发者使用了动态生成js文件的方法,php版本以下:数组
open.php
<?php header('Content-type: application/javascript'); $jsonCallback = htmlspecialchars($_REQUEST ['callback']); //获取请求者自定义的回调函数名 $jsonData ='{"name":"B","age":23}'; //待返回的json数据 echo $jsonCallback . "(" . $jsonData . ")"; //输出jsonp格式的数据,即一行函数调用语句 ?>
额 ..,至于php为何能返回js格式文件,自行百度。
因而网站A用<script src="http://www.B.com/open.php?callback=foo"></script>来请求数据,不须要修改任何变量,返回给A的脚本文件内容是:
foo({"name":"B","age":23}); //所谓的jsonp,就是一句函数调用,数据都被包裹传递到参数中了,千万别穿个马甲就不认识了
网站C就用<script src="http://www.B.com/open.php?callback=blah"></script>来请求数据,返回给C的脚本文件内容是:
blah({"name":"B","age":23});
网站N就用<script src="http://www.B.com/open.php?callback=what"></script>来请求数据,返回给N的脚本文件内容是:
what({"name":"B","age":23});
Problem Solved,你们都取到了指望的数据,而且避免了命名冲突。
jsonp全名叫作json with padding,很形象,就是把json对象用符合js语法的形式包裹起来以使其它网站能够请求获得,也就是将json数据封装成js文件;
json是理想的数据交换格式,但没办法跨域直接获取,因而就将json包裹(padding)在一个合法的js语句中做为js文件传过去。这就是json和jsonp的区别,json是想要的东西,jsonp是达到这个目的而广泛采用的一种方法,固然最终得到和处理的仍是json。因此说json是目的,jsonp只是手段。json总会用到,而jsonp只有在跨域获取数据才会用到。
理解了json和jsonp的区别以后,其实ajax里的跨域获取数据就很好理解和实现了,同源时候并无什么特别的,直接取就行,跨域时候须要拐个弯来达到目的。
附上jquery中ajax请求json数据实例:
(同源):
$.ajax({ url:"persons.json", success:function(data){ console.log(data); //ToDo.. } });
(跨域)
$.ajax({ url:"http://www.B.com/open.php?callback=?", dataType:"jsonp", success:function(data){ console.log(data); //ToDo.. } });
jquery已把jsonp封装进ajax,很合理,由于毕竟绝大多数的jsonp请求都是ajax,关于jquery的ajax具体用法请自行百度,另外要注意的一点就是不一样的网站提供的数据接口的$_REQUEST ['callback']中不必定绝对是callback也多是cb,cbk等,具体使用时务必阅读服务端提供的有关接口使用的详细文档。