本文详细解析JSONP(JSON with Padding)技术,旨在解决浏览器同源策略限制下的跨域数据请求问题。通过对比传统Ajax的跨域失败案例,深入讲解利用script标签src属性加载远程脚本的原理,并展示从手动构造动态script标签到使用jQuery封装接口的完整实现过程。
JSONP是什么
首先介绍JSON这一概念。JSON是一种轻量级的数据传输格式,目前广泛应用于各类Web应用中。由于几乎所有主流编程语言都实现了JSON数据的编码与解析功能,因此现代前后端分离架构普遍采用JSON作为数据传输的标准格式。
那么,JSONP具体指代什么呢?
这里需要引入浏览器的“同源策略”概念。为了保障用户访问安全,现代浏览器强制实施了同源策略,即禁止网页访问与自身不同源的页面。具体而言,在Ajax请求中,浏览器不允许向非同源URL发起请求。例如,运行在www.a.com域名下的页面,其Ajax请求无法访问www.b.com/c.php接口。
JSONP正是为了解决跨域请求限制而诞生的技术方案。其具体实现机制如下:
JSONP原理
虽然Ajax请求受限于同源策略无法跨域,但HTML中script标签的src属性却可以加载跨域的JavaScript脚本。利用这一特性,服务端不再直接返回JSON格式的数据,而是返回一段执行特定函数的JavaScript代码。前端通过script标签的src属性加载该脚本并执行,从而间接获取数据,实现跨域通信。
JSONP具体实现
1. 分析Ajax跨域请求的结果
假设前端代码部署在www.practice.com域名下,尝试使用Ajax发起一个跨域的GET请求。
<!DOCTYPE html>
<html>
<head>
<title>GoJSONP</title>
</head>
<body>
<script type="text/javascript">
function jsonhandle(data){
alert("age:" + data.age + "name:" + data.name);
}
</script>
<script type="text/javascript" src="jquery-1.8.3.min.js">
</script>
<script type="text/javascript">
$(document).ready(function(){
$.ajax({
type : "get",
async: false,
url : "http://www.practice-zhao.com/student.php?id=1",
type: "json",
success : function(data) {
jsonhandle(data);
}
});
});
</script>
</body>
</html>
后端PHP代码部署在www.practice-zhao.com域名下,其功能是简单输出一段JSON格式的数据。
jsonhandle({
"age" : 15,
"name": "John",
当访问前端页面http://www.practice.com/gojsonp/index.html时,Chrome浏览器会报错。

错误提示表明不同源的URL被禁止访问。
2. 使用JSONP方案,移除前端代码中的Ajax请求
在HTML中添加一个script标签,将其src属性指向另一个域名www.practice-zhao.com下的remote.js脚本文件。
<!DOCTYPE html>
<html>
<head>
<title>GoJSONP</title>
</head>
<body>
<script type="text/javascript">
function jsonhandle(data){
alert("age:" + data.age + "name:" + data.name);
}
</script>
<script type="text/javascript" src="jquery-1.8.3.min.js">
</script>
<script type="text/javascript" src="http://www.practice-zhao.com/remote.js"></script>
</body>
</html>
此处调用了跨域的remote.js脚本,该脚本的具体代码如下:
jsonhandle({
"age" : 15,
"name": "John",
})
上述远程JS代码执行了前端预先定义的函数,并弹出了提示框。

3. 进一步修改前端代码
具体代码如下:
<!DOCTYPE html>
<html>
<head>
<title>GoJSONP</title>
</head>
<body>
<script type="text/javascript">
function jsonhandle(data){
alert("age:" + data.age + "name:" + data.name);
}
</script>
<script type="text/javascript" src="jquery-1.8.3.min.js">
</script>
<script type="text/javascript">
$(document).ready(function(){
var url = "http://www.practice-zhao.com/student.php?id=1&callback=jsonhandle";
var obj = $('<script><\/script>');
obj.attr("src",url);
$("body").append(obj);
});
</script>
</body>
</html>
此处动态创建了一个script标签,其src指向跨域的PHP脚本,并将前文定义的JS函数名作为callback参数传入。接下来查看PHP端代码的实现:
<?php
$data = array(
'age' => 20,
'name' => '张三',
);
$callback = $_GET['callback'];
echo $callback."(".json_encode($data).")";
return;
PHP脚本返回了一段JS语句,即:
jsonhandle({
"age" : 15,
"name": "张三",
})
当访问页面时,前端动态添加了一个script标签,src指向PHP脚本,执行返回的JS代码后成功弹出提示框。 总结而言,JSONP将跨域数据访问转化为执行远程JS代码的过程。服务端不再直接返回JSON数据,而是返回一段将JSON数据作为参数传入回调函数的执行代码。
4. 最后,jQuery提供了便捷的JSONP使用方式
具体代码如下:
<!DOCTYPE html>
<html>
<head>
<title>GoJSONP</title>
</head>
<body>
<script type="text/javascript" src="jquery-1.8.3.min.js">
</script>
<script type="text/javascript">
$(document).ready(function(){
$.ajax({
type : "get",
async: false,
url : "http://www.practice-zhao.com/student.php?id=1",
dataType: "jsonp",
jsonp:"callback", //请求php的参数名
jsonpCallback: "jsonhandle",//要执行的回调函数
success : function(data) {
alert("age:" + data.age + "name:" + data.name);
}
});
});
</script>
</body>
</html>
以上即为JSONP原理与应用的完整解析,更多关于JSONP原理和应用的资料请关注本站其它相关文章!