當前位置:
首頁 > 知識 > 前端基礎 動態腳本與JSONP

前端基礎 動態腳本與JSONP

《JS高級程序設計》,發現了很多第一次讀時忽略的、有趣的地方。經典之作,常讀常新。


PART 1 最熟悉的陌生人——動態腳本


對於一些剛接觸前端不久的同學來說,「動態腳本」可能是一個有些陌生的字眼,我也是偶然看高程,才想起同桌的你……不,才注意到這個技術。但事實上,這是每個前端每天都會用到的技術,也是從jQuery到各種狂拽酷炫的前端框架得以運行的基礎技術。那它到底是誰呢?

來看一行代碼:

<script src="jquery.js"></script>

記住一點,網頁歸根到底就是一個HTML頁面,除此之外別無他物。其他如JS、CSS、圖片等,都是頁面上的資源,從屬於這個頁面。JS代碼只有作為script類型的DOM節點的內部文本的形式被添加到網頁上,在瀏覽器解析DOM結構解析到script節點時,才會被執行。動態腳本,顧名思義,是「動態」的JS代碼——「動態」的意思是,不是預先寫在HTML頁面上的,而是在頁面解析的過程中被添加上去的。

動態添加腳本有兩種方法:一是DOM操作,像插入其他類型的DOM節點一樣插入一個script節點到頁面,其內部的JS代碼會被立即執行;二是如jQuery那個例子所示,從某個路徑載入js文件到頁面上來,可以理解為文件中的代碼被複制粘貼到這個script標籤中了,這些代碼會在載入完成後被執行。

舉個栗子:

<!-- 出於簡略,只寫body的代碼 --><body>
<!-- 靜態腳本 -->
<script>
console.log(1);
var scriptDOM = document.createElement("script");
scriptDOM.innerHTML = "console.log(2);"; // 動態腳本的內容
document.body.appendChild(scriptDOM); // 動態插入script DOM節點
console.log(3);
</script>
</body>

這個頁面上有一段靜態腳本,其在執行時會向body插入一個script子節點。用瀏覽器打開這個頁面,console會順序列印出「1 2 3」這三個數字。查看頁面,變成了這樣:

<!-- 出於簡略,只寫body的代碼 -->
<body>
<!-- 靜態腳本 -->
<script>
console.log(1);
var scriptDOM = document.createElement("script");
scriptDOM.innerHTML = "console.log(2);"; // 動態腳本的內容
document.body.appendChild(scriptDOM); // 動態插入script DOM節點
console.log(3);
</script>
<!-- 動態插入的的腳本 -->
<script>console.log(2);</script>
</body>

這個最終頁面有趣的地方在於,包裹「console.log(2);」的script標籤明明排在原來的標籤的後面,但2卻比3先列印出來。事實上,往任何地方插入動態腳本,其中的代碼都會在插入後立刻執行。通過src屬性引入的JS代碼也是如此,一旦載入完成就立刻執行。

這是腳本語言靈活性的絕佳體現呀!想想編譯型語言如C++、Java,所有代碼必須預先編譯好才能執行,無法做到像JS這樣,不用編譯不說,還可以在原本的代碼執行到一半時,忽然插進來一堆新代碼並且立即得到執行;就好比原本宴會邀請到了99個賓客,飯吃到一半,忽然來了個不速之客,還是個自來熟,坐下就開始與眾人談笑風生、觥籌交錯,於是東道主JavaScript順手就把賓客人數改成了100,毫無違和感;若是換成C++或Java做東,只會在宴會開始後把所有入口全部封死,不再允許任何人進入。

PART 2 動態腳本的應用:JSONP



「跨域」是前端面試中幾乎必考的問題,而JSONP是一個比較簡單好使的解決方案。

JSONP誕生的背景是,「跨域」只是AJAX所受的安全策略限制,只要域名協議這3項有1項不一致,瀏覽器就禁止發送AJAX請求。而像<script><img><link>這類標籤的src屬性不受此限,可以填寫任意域名的地址(想想jQuery的CDN地址,還有一堆圖床網站……)。於是聰明的前端攻城獅們想到了利用動態腳本來獲取json數據的套路,名曰JSON Padding,意思是「JSON填充」。

那具體怎麼個做法呢?分三步

步驟1

讓伺服器端略改下代碼:當一個get請求的查詢參數里有callback一項時,譬如一個URL長這樣:

http://someurl.com/data?callback=handler

那麼伺服器就不要直接把JSON文件作為響應內容了,而是返回一個動態生成的JS文件,其中的代碼是

handler({JSON數據});

其實就是一個handler函數的調用,同時把JSON作為參數「填充」進去。

步驟2

回到前端。定義好負責處理JSON數據的handler函數:

function handler(json) {
// 處理json數據
}

步驟3

在需要跨域獲取數據時,向頁面插入一個script DOM元素:

var script= document.createElement("script");
script.src = "http://someurl.com/data?callback=handler";
document.body.appendChild(script);

這個script元素的src屬性值帶有一個callback查詢參數,於是伺服器會返回步驟1中的代碼,這段代碼被下載完成後立刻執行,handler恰好是已經定義好的函數,而夢寐以求的跨域JSON數據就這樣作為handler的實參被傳到了當前頁面上!

最後是兩點注意事項:

1. 用這種方法可以請求任何類型的數據,不限制為JSON,只是因為JSON最常用,所以命名為JSONP。

2. JSONP是為了幫AJAX繞開跨域限制而使用的一種技巧,它本身跟AJAX沒有半毛錢關係,在不支持AJAX的瀏覽器上照樣可以用JSONP技術。

文章摘自博客園


中公優就業 幫你成就職業夢:

IT教育專業培訓:https://www.ujiuye.com/

IT職業在線教育:https://xue.ujiuye.com/

大數據時代下做java開發工程師:https://www.ujiuye.com/zt/java/?wt.bd=lsw44106tt

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 IT優就業 的精彩文章:

JAVA 線程的幾種狀態
Spark運算元講解(上)
Spark運算元講解(下)
深入淺出數據結構C語言版——有關排序演算法的分析
盤點互聯網黑色產業

TAG:IT優就業 |