我理解JSON,但不理解JSONP。维基百科关于JSON的文档是JSONP的最高搜索结果。上面写着:
JSONP或“带填充的JSON”是一个JSON扩展,其中前缀被指定为调用本身的输入参数。
嗯?什么电话?这对我来说毫无意义。JSON是一种数据格式。没有电话。
第二个搜索结果来自一个叫雷米的人,他写了关于JSONP的文章:
JSONP是脚本标记注入,将服务器的响应传递给用户指定的函数。
我可以理解,但这仍然没有任何意义。
那么什么是JSONP?为什么创建它(它解决了什么问题)?我为什么要用它?
附录:我刚刚在维基百科上为JSONP创建了一个新页面;根据jvenema的回答,它现在对JSONP有了清晰而透彻的描述。
因为您可以要求服务器为返回的JSON对象添加前缀。例如
function_prefix(json_object);
以便浏览器将JSON字符串作为表达式“内联”求值。这一技巧使服务器可以直接在客户端浏览器中“注入”javascript代码,并且绕过“同源”限制。
换句话说,您可以实现跨域数据交换。
通常,XMLHttpRequest不允许直接进行跨域数据交换(需要通过同一域中的服务器),而:
<script src=“some_other_domain/some_data.js&prefix=function_prefix>`可以从不同于源域的域访问数据。
同样值得注意的是:即使在尝试这种“技巧”之前,服务器应该被认为是“可信的”,但对象格式等可能改变的副作用也可以得到控制。如果使用function_prefix(即正确的js函数)接收JSON对象,则所述函数可以在接受/进一步处理返回的数据之前执行检查。
其实并不太复杂。。。
假设你在domain example.com上,你想向domain example.net发出请求。要做到这一点,你需要跨越域边界,这在大多数浏览器中是不允许的。
绕过此限制的一项是<script>标记。当您使用脚本标记时,域限制将被忽略,但在正常情况下,您无法对结果执行任何操作,脚本只会得到评估。
输入JSONP。当您向启用了JSONP的服务器发出请求时,您会传递一个特殊参数,该参数会告诉服务器有关您的页面的一些信息。这样,服务器能够以页面可以处理的方式很好地包装其响应。
例如,假设服务器需要一个名为callback的参数来启用其JSONP功能。那么您的请求将如下所示:
http://www.example.net/sample.aspx?callback=mycallback
如果没有JSONP,这可能会返回一些基本的JavaScript对象,如下所示:
{ foo: 'bar' }
然而,使用JSONP,当服务器接收到“回调”参数时,它会稍微不同地包装结果,返回如下内容:
mycallback({ foo: 'bar' });
如您所见,它现在将调用您指定的方法。因此,在页面中,您可以定义回调函数:
mycallback = function(data){
alert(data.foo);
};
现在,当加载脚本时,将对其求值,并执行您的函数。瞧,跨域请求!
还值得注意的是JSONP的一个主要问题:您失去了对请求的大量控制。例如,没有“好”的方法可以取回正确的故障代码。因此,您最终使用计时器来监视请求等,这总是有点可疑。JSONRequest的提议是允许跨域脚本编写、维护安全性和允许正确控制请求的一个很好的解决方案。
目前(2015年),CORS是与JSONRequest相比的推荐方法。JSONP对于较旧的浏览器支持仍然有用,但考虑到安全问题,除非您别无选择,否则CORS是更好的选择。
在理解JSONP之前,您需要了解JSON格式和XML。目前,web上最常用的数据格式是XML,但XML非常复杂。这使得用户不方便处理嵌入在网页中的内容。
为了使JavaScript能够轻松地交换数据,即使作为数据处理程序,我们也根据JavaScript对象使用了措辞,并开发了一种简单的数据交换格式,即JSON。JSON可以用作数据,也可以用作JavaScript程序。
JSON可以直接嵌入JavaScript中,使用它们可以直接执行某些JSON程序,但由于安全限制,浏览器沙盒机制禁用跨域JSON代码执行。
为了使JSON可以在执行后传递,我们开发了一个JSONP。JSONP通过JavaScript回调功能和<script>标记绕过浏览器的安全限制。
简而言之,它解释了JSONP是什么,它解决了什么问题(何时使用它)。