摘要:就這樣被發(fā)明了,利用的屬性不受同源策略的控制,作弊般地巧妙地逃過(guò)了瀏覽器的這一限制。然后,聲明這個(gè)回調(diào)函數(shù)。
這是我在13年初寫(xiě)的文章,當(dāng)時(shí)懵懵懂懂寫(xiě)下了自己對(duì)JSONP的理解。
文章原文
博客 歡迎訂閱
提到JSONP,我當(dāng)時(shí)在網(wǎng)上找了無(wú)數(shù)帖子也沒(méi)有看懂它。那些文章大同小異,都是講到JSONP原理以后就戛然而止,把我們這些初學(xué)者搞得云里霧里。所以,寫(xiě)下這篇文章,希望對(duì)大家有幫助!
為什么要有JSONP回答這個(gè)問(wèn)題之前,大家先想想什么是AJAX,JSONP就是一種能夠解決AJAX辦不到的事情而存在的一種取數(shù)據(jù)的技術(shù)。什么事情是AJAX辦不到的呢?就是跨域!
跨域:顧名思義,就是當(dāng)前網(wǎng)頁(yè)的地址和我們要取的數(shù)據(jù)地址不在一個(gè)域下。這是因?yàn)闉g覽器都有一個(gè)“同源策略”— 兩個(gè)頁(yè)面的域名必須在同域的情況下,才能允許通信。
怎么才算一個(gè)域呢?
相同域名,相同端口,相同協(xié)議(因?yàn)椴皇沁@里的重點(diǎn),大家可以請(qǐng)教Google)
“同源策略”的意義:“同源策略”有效地阻止了一些危險(xiǎn)行為,比如你進(jìn)入www.aaa.com,同時(shí)瀏覽器又開(kāi)了一個(gè)www.bbb.com,如果這個(gè)www.bbb.com是一個(gè)木馬網(wǎng)站,在沒(méi)有“同源策略”的情況下,它就可能嵌入一些代碼,來(lái)取得你在www.aaa.com的信息(因?yàn)檫@時(shí)兩個(gè)頁(yè)面是可以通信的) 。而正是因?yàn)橛辛恕巴床呗浴保瑒偛趴梢酝ㄐ诺那闆r才不會(huì)發(fā)生。
“同源策略”帶來(lái)的麻煩:上面的例子是我們?cè)诓恢榈那闆r下,保護(hù)我們的網(wǎng)絡(luò)安全的,但如果我們就是要讓www.aaa.com取得www.bbb.com上的數(shù)據(jù),行不行呢?答:不行!還是因?yàn)椤蓖床呗浴保∥覀兿霃淖约盒湃蔚木W(wǎng)頁(yè)上取得數(shù)據(jù)都不行,這可怎么辦呢?
JSONP出現(xiàn)在需要跨域通信的歲月里,一些卓越的前端工程師們想到了這個(gè)”作弊”的辦法來(lái)逃避”同源策略”?!蓖床呗浴彪m然很厲害,阻止了一個(gè)頁(yè)面到另一個(gè)頁(yè)面的通信,可是src指向的路徑它放過(guò)了,提到src,大家是不是想起了
www.bbb.com/abc.js中:
abc({"name":"risker","age":24});
頁(yè)面會(huì)彈出risker,有感覺(jué)了么?
JSONP是這樣工作的:像前面所說(shuō)的那樣,我們可以取到www.bbb.com/abc.js,里面是一個(gè)abc函數(shù),這個(gè)函數(shù)也會(huì)被加載到www.aaa.com。加載完成后,就應(yīng)該執(zhí)行abc了,然后我們?cè)?b>www.aaa.com定義abc函數(shù),這個(gè)函數(shù)里寫(xiě)一些處理數(shù)據(jù)的語(yǔ)句。這樣其實(shí)就簡(jiǎn)單地實(shí)現(xiàn)了跨域訪問(wèn)數(shù)據(jù)了,這也就是JSONP的原理了。而JSON with Padding的意思,就是abc(json)中的json:
abc({"name":"risker","age":24})。
這個(gè)JSON對(duì)象被包在abc這個(gè)函數(shù)中當(dāng)作參數(shù)來(lái)被處理,而JSON with Padding這個(gè)詞很形象地形容了這個(gè)過(guò)程。
JSONP的簡(jiǎn)單實(shí)例在網(wǎng)上能找到的JSON基本只是介紹到這里就完了,但是這讓初學(xué)者看不到一個(gè)實(shí)實(shí)在在的例子。所以下面才是這篇文章和其他網(wǎng)上介紹JSON文章不一樣的地方,我?guī)Ыo大家一個(gè)例子!
大家一定對(duì)百度的自動(dòng)搜索框有印象,它就是一個(gè)JSONP的實(shí)例:
先查看demo
分析一下:
1.分析數(shù)據(jù)地址回顧上面的例子,我們首先要知道數(shù)據(jù)的來(lái)源地址,就是上面的www.bbb.com/abc.js里的數(shù)據(jù)。在Chrome中查看Network。然后隨便在搜索框里輸入點(diǎn)什么,比如s,觀察Network里是不是多了東西,點(diǎn)開(kāi)它,就是我們輸入“s”后傳回的數(shù)據(jù)了:
這個(gè)地址是http://suggestion.baidu.com/su?wd=S&p=3&cb=window.bdsug.sug&from=superpage&t=1365392859833 , 我們分析一下,wd后面是s,那就可以斷定百度定義wd是搜索的關(guān)鍵字,cb是一個(gè)回調(diào)函數(shù),其他的對(duì)我們就不重要了?;卣{(diào)函數(shù)是我們?nèi)〉綌?shù)據(jù)要后執(zhí)行的函數(shù),相當(dāng)于我們上面的abc函數(shù)。它是可以自己取名的。像http://suggestion.baidu.com/su?wd=S&p=3&cb=succ&from=superpage表示取到數(shù)據(jù)后執(zhí)行succ函數(shù):
這樣,我們的數(shù)據(jù)就包在了succ函數(shù)里做一個(gè)參數(shù),再次證明了JSON with Padding 的原理。
2.做