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>
<?phpecho 'test("js++")';
phpsyudy 通过www运行才可以成功,用服务器解析php代码,解析成js代码,浏览器端解析不了php代码

<?php$dataecho '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=testoScript.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有很长的后缀,把后缀都给删除了,照样可以跳转

