JSONP
JSONP:JSON with Padding (跨域获取JSON数据的一种非官方的使用方式)
JSON和JSONP不是一个类型
JSON是数据交换格式
JSONP是一种跨域获取JSON数据的技术
JSONP抓取的资源并不直接是JSON数据,而是带有JSON数据参数的函数执行
客户端期望的返回的:{“name”:”Jacky”,”age”:”18”}
JSONP实际返回的:callback({“name”:”Jacky”,”age”:”18”})
返回不是json类型的数据也可以,img,xml,数组等其它类型数据都可以
jsonp抓取资源不是json数据,是带有json数据或者带有资源参数的一个函数执行,
把数据放在一个函数参数中
在json的基础上做了一个扩展padding,jsonp(adding)
同源策略给谁走了后门
谁可以不受退同源策略的影响,如果同源策略不可以解决,那会非常麻烦
同源策略在浏览器端给一些资源开了后门
- img的src引入不同源的图片资源
2. link的href引入不同源的样式资源
3. iframe的src引入不同源的网页资源
4. script的src引入不同源的脚本文件资源
总结
带src的,带href属性的标签,不受同源策略影响
图片
<img src="https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png" alt="">
右键复制图像链接,给src标签赋值
http://localhost:63342/与src的链接
https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png
并不同源,但却可以得到图片资源,说明是跨过了同源的限制
cdn搜索
https://fontawesome.dashgame.com/
搜索font awesome cdn
引入css
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<!--<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">-->
<body>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<img src="https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png" alt="">
<i class="fa fa-angle-double-down"></i>
</body>
</html>
在scources可以看到是否引入资源成功
iframe、script引入资源
index.html
<script src="./js/index.js"></script>
<!--引入index代码,相当于如下代码,相当于新开一个script,并把index.js中的代码重写一遍-->
<!--<script>
var a = 1;
</script>-->
<script !src="">
console.log(a);
</script>
运行网页html,结果如下
打印a的结果1
index.js
var a=1;
引入index代码,相当于如下代码,相当于新开一个script,并把index.js中的代码重写一遍
相当于
<script>
var a = 1;
</script>
<script !src="">
console.log(a);
</script>
把index.js后缀名改成txt,再引入照样可以运行,打印1
<script src="js/index.txt"></script>
<script !src="">
console.log(a);
</script>
txt现象理解
无论后缀名是什么,只在乎里面内容是什么,与后缀名无关,因为script标签本身就是引入脚本的,script会只看里面的内容,因为script本身就是引入脚本的
因为script标签本身就是拿来解析脚本或者写脚本用的,文件后缀名对于script标签来说本身根本不重要,因为引入进来的东西,会把它当做脚本,只要一引入进来首先会看里面的内容,看里面的内容是不是符合脚本,是不是符合js脚本,是不是符合ecma规范,预编译,只要内容符合脚本就正常解析,如果里面有错误,再报错。如果不符合ecma规范就报错
后缀名对于script来说就没有用处,有些大厂js文件,后面没有后缀名
不是script会优先把文件当做js代码来解析,不能这么理解,也不能说没有道理
如果一个文件没有后缀,那么window会当成是txt文件
html
<script !src="">
function test(str){
console.log(str);
}
</script>
<script src="./js/index.js"></script>
index.js
test("js++")
可以运行,结果
在html写代码定义,在js写执行,也可以运行
<script src="./js/index.js"></script>
<script !src="">
function test(str){
console.log(str);
}
</script>
<script !src="">
function test(str){
console.log(str);
}
</script>
<script src="./js/index.js"></script>
<script src="./server/index.php"></script>
<?php
echo 'test("js++")';
phpsyudy 通过www运行才可以成功,用服务器解析php代码,解析成js代码,浏览器端解析不了php代码
<?php
$data
echo 'test($data)';
如果把从数据库中取出来的$data数据,通过test方法加参数传过来,可以通过script标签接收到,test($data),方法+参数
jsonp
<script src="http://test:jsplusplus.com/jsonp/jsonp.js"></script>
<script !src="">
console.log(a)
</script>
jsonp.js
var a=1;
打印a=1
jsonp.js
var a = 1;
function getParams() {
var path = document.getElementById('jsonpScript').src,
callback = path.match(/cb=(.*)/)[1];
switch (callback) {
case 'test1':
test1('test1');
break;
case 'test2':
test2('test2');
break;
case 'test3':
test3('test3');
break;
default:
test1('test1');
}
}
getParams();
index.html
<script !src="">
function test1(str){
console.log(str);
}
function test2(str) {
console.log(str);
}
function test3(str) {
console.log(str);
}
</script>
<script src="http://test:jsplusplus.com/jsonp/jsonp.js?cb=test3" id="jsonpScript"></script>
<script !src="">
console.log(a)
</script>
通过改变改变cb=test1|test2|test3,改变方法
jsonp是一个无比简单的东西,之所以有人学不会,是因为基础没有弄明白,最基础的没有弄好
index.html引用外界脚本script
分析
写了三个函数,通过cb把函数名称给服务器上的js代码,js代码通过运行,通过id得到元素,可以得到元素的src属性,得到字符串http://test:jsplusplus.com/jsonp/jsonp.js?cb=test3,通过正则表达式,提取出来test3,通过switch判断,运行代码,通过get传值把数据传给页面
jsonp
test({"name":"Jacky","age":"35","sex":"male"});
<script !src="">
function test(str){
console.log(str);
}
</script>
<script src="http://test:jsplusplus.com/jsonp/jsonp.js?cb=test" id="jsonpScript"></script>
<script !src="">
console.log(a)
</script>
jsonp.js
$.ajax({
url: 'http://test.jsplusplus.com/get_courses.php',
type : 'post',
data : {
status:1
},
success : function(data){
test(data);
}
})
<script !src="">
function test(data){
console.log(data);
}
</script>
<script src="http://test:jsplusplus.com/jsonp/jsonp.js" ></script>
index通过src引入jsonp.js代码,jsonp发起ajax请求,把ajax请求的数据通过index中的方法,把参数传过去
这就相当于
<script !src="">
function test(str) {
console.log(str);
}
</script>
<script !src="">
test('我是test源下的jsonp.js');
</script>
<script src="http://test:jsplusplus.com/jsonp/jsonp.js?cb=test"></script>
jsonp.js
引入脚本,相当于新建脚本,把代码复制粘贴到引入的地方,等价替换
test('我是test源下的jsonp.js');
<script !src="">
function test(data) {
console.log(data);
}
</script>
<script src="http://test:jsplusplus.com/jsonp/jsonp.php?cb=test"></script>
不管脚本是前端的还是后端,只要返回的是test(‘js++’),就可以解析,后缀名是js、php都可以,只关心最终返回的东西,如果不符合ecma的规范,会报错
jsonp都是后端写好的,与后端商量好,前端要接口
cb、callback商量好
封装
<script src="http://test:jsplusplus.com/jsonp/jsonp.php?cb=test1"></script>
<script src="http://test:jsplusplus.com/jsonp/jsonp.php?cb=test2"></script>
<script src="http://test:jsplusplus.com/jsonp/jsonp.php?cb=test3"></script>
请求多个资源,需要多个script引入不同的接口,需要写很多script,这样做不太合理
<button id="btn">获取资源</button>
<script !src="">
var oBtn=document.getElementById('btn');
oBtn.onclick=function (){
oSCript=document.createElement('script');
oSCript.src='http://test.jsplusplus.com/jsonp/jsonp.php?cb=test';
document.body.appendChild(oSCript);
document.body.appendChild(oSCript);
}
function test(data){
console.log(data)
}
</script>
不用写延迟,因为js执行时,是一行一行执行的
cb=test得与function test一致就行
动态创建,script标签
百度搜索就是用jsonp获取资源的
百度是个跨域请求sp0.baidu.com
jquery封装的jsonp获取
把jsonpCallback注释掉
就有这个乱码了
百度就是用的jquery的ajax封装的jsonp获取,没有自己封装
封装的ajax中添加jsonp的封装
在封装的ajax中添加,以下代码
jsonp = opt.jsonp || 'cb',
jsonpCallback = opt.jsonpCallback || 'jQuery' + randomNum() + '_' + new Date().getTime();
if(dataType.toUpperCase() === 'JSONP' && method !== 'GET') {
throw new Error('如果dataType为JSONP,请您将type设置成GET');
}
if(dataType.toUpperCase() === 'JSONP') {
var oScript = document.createElement('script');
// xxx.domain.com/xxx.php?cb=test
// xxx.domain.com/xxx.php?wd=xxx&cb=test
oScript.src = url.indexOf('?') === -1
? url + '?' + jsonp + '=' + jsonpCallback
: url + '&' + jsonp + '=' + jsonpCallback;
document.body.appendChild(oScript);
document.body.removeChild(oScript);
window[jsonpCallback] = function(data){
success(data);
}
}
//随机数,上面的随机数
function randomNum(){
var str = '';
for(var i = 0; i < 20; i++) {
str += Math.floor( Math.random() * 10);
}
return str;
}
总结
jsonp只有get请求才行,post不行,因为后面没有参数
利用src是没有限制的,,在src中写后端脚本,让后端脚本拼接出来,要的前端的脚本,也就是函数执行,拼接好,返回响应给客户端,data作为函数的参数,传过来
拼接字符串
百度联想词
浏览器操作
清空没有信息
点击红色按钮停止记录网络日志,再点开记录网络日志,清零网络日志
现在的百度响应
基本上输入一个字母就请求一次,上下两个差了一个n
之前的百度响应,与现在的不一样
复制请求url,到浏览器地址栏
复制请求url,到浏览器地址栏,跳转,结果显示一段文本,这是fehelper解析后的
g联想词
不解析应该是这样的格式
搜索京东,url有很长的后缀,把后缀都给删除了,照样可以跳转