什麼是js跨域吶?
js跨域是指透過js在不同的域之間進行數據傳輸或通信,例如用ajax向一個不同的域請求數據,或者透過js獲取頁面中不同域的框架中(iframe)的數據。只要協定、網域、連接埠有任何一個不同,都被當作是不同的網域。
要解決跨域的問題,我們可以使用以下幾種方法:
一、透過jsonp跨域
在js中,我們直接用XMLHttpRequest請求不同域上的資料時,是不行的。但是,在頁面上引入不同網域上的js腳本檔案卻是可以的,jsonp正是利用這個特性來實現的。
例如,有個a.html頁面,它裡面的程式碼需要利用ajax取得一個不同網域上的json數據,假設這個json資料位址是http://example.com/data. php,那麼a.html中的程式碼就可以這樣:
我們看到取得資料的位址後面還有一個callback參數,照慣例是用這個參數名,但是你用其他的也一樣。當然如果取得資料的jsonp位址頁面不是你自己能控制的,就得按照提供資料的那一方的規定格式來操作了。
因為是當做一個js檔案來引入的,所以http://example.com/data.php回傳的必須是一個能執行的js文件,所以這個頁面的php程式碼可能是這樣的:
最終那個頁面輸出的結果是:
所以透過http://example.com/data.php?callback=dosomething得到的js文件,就是我們之前定義的dosomething函數,並且它的參數就是我們需要的json數據,這樣我們就跨域獲得了我們需要的數據。
這樣jsonp的原理就很清楚了,透過script標籤引入一個js文件,這個js文件載入成功後會執行我們在url參數中指定的函數,並且會把我們需要的json資料作為參數傳入。所以jsonp是需要伺服器端的頁面進行對應的配合的。
知道jsonp跨域的原理後我們就可以用js動態產生script標籤來進行跨域操作了,而不用特意的手動的書寫那些script標籤。如果你的頁面使用jquery,那麼透過它封裝的方法就能很方便的來進行jsonp操作了。
原理是一樣的,只不過我們不需要手動的插入script標籤以及定義回掉函數。 jquery會自動產生一個全域函數來取代callback=?中的問號,之後取得到資料後又會自動銷毀,其實就是起一個臨時代理函數的作用。 $.getJSON方法會自動判斷是否跨域,不跨域的話,就呼叫普通的ajax方法;跨域的話,則會以非同步載入js檔案的形式來呼叫jsonp的回呼函數。
2、透過修改document.domain來跨子域
瀏覽器都有一個同源策略,其限制之一就是第一種方法中我們說的不能透過ajax的方法去請求不同來源中的文件。 它的第二個限制是瀏覽器中不同域的框架之間是不能進行js的交互操作的。有一點需要說明,不同的框架之間(父子或同輩),是能夠獲取到彼此的window對象的,但蛋疼的是你卻不能使用獲取到的window對象的屬性和方法(html5中的postMessage方法是一個例外,還有些瀏覽器例如ie6也可以使用top、parent等少數幾個屬性),總之,你可以當做是只能獲取到一個幾乎無用的window對象。例如,有一個頁面,它的位址是http://www.example.com/a.html , 在這個頁面裡面有一個iframe,它的src是http://example.com/b.html, 很顯然,這個頁面與它裡面的iframe框架是不同域的,所以我們是無法透過在頁面中書寫js程式碼來取得iframe中的東西的:
這時候,document.domain就可以派上用場了,我們只要把http://www.example.com/a.html 和 http://example.com/b.html這兩個頁面的document.domain都設為相同的網域就可以了。但要注意的是,document.domain的設定是有限制的,我們只能把document.domain設定成自身或更高一級的父域,而主域必須相同。例如:a.b.example.com 中某文檔的document.domain 可以設成a.b.example.com、b.example.com 、example.com中的任一個,但是不可以設成c.a.b.example.com,因為這是當前域的子域,也不可以設成baidu.com,因為主域已經不相同了。
在頁面 http://www.example.com/a.html 設定document.domain:
在頁面 http://example.com/b.html 中也設定document.domain,而且這也是必須的,雖然這個文件的domain就是example.com ,但是還是必須顯示的設定document.domain的值:
這樣我們就可以透過js存取到iframe中的各種屬性和物件了。
不過如果你想在http://www.example.com/a.html 頁面中透過ajax直接要求http://example.com/ b.html 頁面,即使你設定了相同的document.domain還是不行的,所以修改document.domain的方法只適用於不同子網域的框架間的互動。如果你想透過ajax的方法去與不同子網域的頁面交互,除了使用jsonp的方法外,還可以用一個隱藏的iframe來做一個代理。原理就是讓這個iframe載入一個與你想要透過ajax取得資料的目標頁面處在相同的網域的頁面,所以這個iframe中的頁面是可以正常使用ajax去取得你要的資料的,然後就是透過我們剛剛講得修改document.domain的方法,讓我們能透過js完全控制這個iframe,這樣我們就可以讓iframe去發送ajax請求,然後收到的資料我們也可以獲得了。
3、使用window.name來進行跨域
window物件有name屬性,該屬性有個特徵:即在一個視窗(window)的生命週期內,視窗載入的所有的頁面都是共享一個window.name的,每個頁面對window. name都有讀寫的權限,window.name是持久存在一個視窗載入過的所有頁面中的,並不會因為新頁面的載入而重置。
例如:有一個頁a.html,它裡面有這樣的程式碼:
再看b.html頁面的程式碼:
a.html頁面載入後3秒,跳到了b.html頁面,結果為:
我們看到在b.html頁面上成功取得到了它的上一個頁面a.html給window.name設定的值。如果在之後所有載入的頁面都沒對window.name進行修改的話,那麼所有這些頁面取得到的window.name的值都是a.html頁面設定的那個值。當然,如果有需要,其中的任何一個頁面都可以對window.name的值進行修改。注意,window.name的值只能是字串的形式,這個字串的大小最大能允許2M左右甚至更大的一個容量,取決於不同的瀏覽器,但一般是夠用了。
上面的例子中,我們用到的頁面a.html和b.html是處於同一個域的,但是即使a.html與b.html處於不同的域中,上述結論同樣是適用的,這也正是利用window.name進行跨域的原理。
下面就來看看具體是怎麼樣透過window.name來跨域取得資料的。還是舉例說明。
例如有一個www.example.com/a.html頁,需要透過a.html頁面裡的js來取得另一個位於不同網域上的頁面www.jb51.net/data.html裡的資料。
data.html頁面裡的程式碼很簡單,就是給目前的window.name設定一個a.html頁面想要得到的資料值。 data.html裡的程式碼:
那麼在a.html頁面中,我們要怎麼把data.html頁面載入進來呢?顯然我們不能直接在a.html頁面中透過改變window.location來載入data.html頁面,因為我們想要即使a.html頁面不跳轉也能得到data.html裡的資料。答案就是在a.html頁面中使用一個隱藏的iframe來充當一個中間人角色,由iframe去獲取data.html的數據,然後a.html再去得到iframe獲取到的數據。
充當中間人的iframe想要取得到data.html的透過window.name設定的數據,只需要把這個iframe的src設為www.jb51.net/data.html 就行了。然後a.html想要得到iframe所取得的數據,也就是想要得到iframe的window.name的值,還必須把這個iframe的src設為跟a.html頁面同一個域才行,不然根據前面講的同源策略,a.html是不能存取到iframe裡的window.name屬性的。這就是整個跨域過程。
看下a.html頁面的程式碼:
上面的程式碼只是最簡單的原理演示程式碼,你可以對使用js封裝上面的過程,例如動態的創建iframe,動態的註冊各種事件等等,當然為了安全,獲取完數據後,還可以銷毀作為代理的iframe。網路上也有很多類似的現成程式碼,有興趣的可以去找一下。
透過window.name來進行跨域,就是這樣子的。
4、使用HTML5中新引進的window.postMessage方法來跨域傳送資料
window.postMessage(message,targetOrigin) 方法是html5新引進的特性,可以使用它來向其它的window物件發送訊息,無論這個window物件是屬於同源或不同來源,目前IE8 、FireFox、Chrome、 Opera等瀏覽器都已經支援window.postMessage方法。
呼叫postMessage方法的window對像是指要接收訊息的那一個window對象,該方法的第一個參數message為要傳送的訊息,型別只能為字串;第二個參數targetOrigin用來限定接收訊息的那個window物件所在的域,如果不想限定域,可以使用通配符* 。
需要接收訊息的window對象,可是透過監聽自身的message事件來取得傳過來的訊息,訊息內容儲存在該事件對象的data屬性中。
上面所說的向其他window物件發送訊息,其實就是指一個頁面有幾個框架的那種情況,因為每個框架都有一個window物件。在討論第二種方法的時候,我們說過,不同域的框架間是可以取得到對方的window物件的,而且也可以使用window.postMessage這個方法。下面看一個簡單的範例,有兩個頁面
我們運行a頁面後得到的結果:
我們看到b頁面成功的收到了訊息。
使用postMessage來跨域傳送資料還是比較直覺和方便的,但是缺點是IE6、IE7不支持,所以用不用還得根據實際需要來決定。
除了以上幾種方法外,還有flash、在伺服器上設定代理頁面等跨域方式,這裡就不做介紹了。
以上四種方法,可以依照專案的實際情況來進行選擇應用,希望這篇文章對大家的學習有所幫助。

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

禪工作室 13.0.1
強大的PHP整合開發環境

SublimeText3 Linux新版
SublimeText3 Linux最新版

Atom編輯器mac版下載
最受歡迎的的開源編輯器

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!