一,同源策略其實網絡的安全基石,既:http://www.baidu.com:80協議(http或者HTTPS或者ws或者wss)、域名(www.baidu.com)、端口(默認80,能夠不寫 https默認是443端口)相同。防止一些信息被人盜取或者破壞,具體的概念在這裏就不詳細述說了,你們可參考阮一峯大師的文章(http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html)。javascript
二,你們有沒有注意下面的這種狀況:html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
img{
width:200px;
height: 100px;
}
</style>
</head>
<body>
<img src="https://mdn.mozillademos.org/files/12676/star.svg" alt="">
</body>
</html>
上面代碼紅色區域src 引用的是https協議下的一個網路圖片,可是你把代碼在本地瀏覽器打開的時候,也能夠請求到圖片,看一下圖片的對比。也就是說下面兩個連接是在不一樣域狀況下打開的,可是能夠跨域請求到想要的圖片。也就是說咱們能夠利用src的屬性進行跨域請求數據,也就是說 script標籤也能夠跨域請求相應的資源,如:<script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>前端
三,先讓你們看代碼<!DOCTYPE html>java
<html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> img{ width:200px; height: 100px; } </style> <script>
function a(){
alert(1)
} </script> </head> <body> <script> a(); </script> </body> </html>
你們用瀏覽器打開頁面,會看到頁面彈出了1,注意看標記爲紅色的區域。是在兩個不一樣的script一個賦值一個請求,這樣是能夠請求道的。說這個的目的是爲了爲下面封裝jsonp 作解釋。jquery
四,先看封裝好的jsop函數:原理:前端定義個全局的函數,動態建立script,利用src去請求後臺的資源,只是後臺返回的是一個參數爲前端所需數據的前端全局函數的調用。看下圖:請求道的是一個函數的調用。json
下面我對代碼裏①到⑦作一一的解釋。跨域
①:cbName是爲了跟後臺建立一個相應的規則協議,跨域請求的時候,容許用戶傳遞一個callback參數給服務端,而後服務端返回數據時會將這個callback參數做爲函數名來包裹住JSON數據,客戶端能夠隨意定製本身的函數(fnName)來自動處理返回數據了。 瀏覽器
②:每次請求相同的src瀏覽器會緩衝,因此在uri後面添加時間戳,防止二次請求的時候,返回不是最新想要的數據。安全
③:url路徑不容許帶有小數點,因爲時間戳帶有小數點,要把小數點替換成空。網絡
④:src去請求數據時 能夠自定義取數據的時間,超過規定的時間,就定義爲請求超時。請求超時就不要再讓window.fn繼續執行處理數據,window[fnName] = null。
⑤:跨域請求過來的是自定義的回調函數的調用,當回調調用成功後,也就是調用了全局的window[fnName]函數(這函數裏也能夠繼續回調(success)函數)來處理數據,達到本身想要的數據類型或者舍取。因爲獲取成功後相應超時的限制意義就不存在了,要把定時器關閉。並把建立好的script對象刪除。
<script>
fnName (json) {//window下的函數
......XXXX
}
</script>
再在動態建立的srcpt裏,請求到後臺返回數據(數據爲:函數的直接調用)。
<script src="https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=%E7%8E%8B%E6%B5%A9&cb=jsonp_p08777009389580372#"></script> === window.fnName();
⑥:拼接url,到達協議的要求,即:後臺返回jsonp回調函數的要求:關鍵字、cbName及其餘請求參數。
⑦:dom操做建立添加script標籤,動態請求數據,成功後直接刪除。
function jsonp(options){ if(!options.url){return;} options = options||{}; options.data = options.data||{}; options.cbName = options.cbName||'cb';//① options.timeout = options.timeout||10000; var fnName = 'jsonp_p'+Math.random();//② var fnName = fnName.replace('.','');//③ var timer = setTimeout(function(){//④ options.error&&options.error(); window[fnName] = null; },options.timeout); window[fnName] = function(json){ //⑤ options.success&&options.success(json); clearTimeout(timer); document.getElementsByTagName('head')[0].removeChild(oS); }; //cb = show options.data[options.cbName] = fnName; var arr = []; for(var name in options.data){//⑥ arr.push(name+'='+options.data[name]); } var oS = document.createElement('script');//⑦ oS.src = options.url+'?'+arr.join('&'); document.getElementsByTagName('head')[0].appendChild(oS); }
五,以上就是本人對jsonp的理解,因爲小生纔能有限,寫的不到位的地方請大神多多指教,本人將不吝賜教,謝謝!