最近在寫bug的過程當中發現一個有意思的事,我把它稱之爲" sessionStorage
'繼承' "。咱們能夠按如下作法復現這一過程:html
打開一個頁面(咱們稱之爲a頁面),在控制檯執行web
sessionStorage.a = 'a'; window.open(window.location.href); // 獲得b頁面
咱們把新打開的頁面叫作b頁面,而後咱們在b頁面控制檯執行瀏覽器
sessionStorage // 直接這麼寫是沒有問題的,至關與獲取window對象的sessionStorage屬性 // 輸出 {a: "a", length: 1}
按照個人認知,通常認爲sessionStorage
是頁面級的,頁面與頁面之間互不影響。
對於上面這個例子,我期待的輸出應該只有一個length
屬性,而不是這種相似'繼承'的表現。
這和個人認知是有差別的,我得查一下。在查文檔以前,咱們先對這個問題進行簡單的探索與分析。cookie
我按照個人認知測試了一下:session
在a頁面中執行dom
sessionStorage.a = 'a';
而後複製a頁面的url,新建一個tab頁打開這個url,執行測試
sessionStorage // 輸出 {length: 0}
嗯,個人認知也對,只是不全面,缺少特定場景下的補充。而後我對這個進行了進一步的探索。
在測試一的基礎上我繼續:url
在a頁面控制檯執行code
sessionStorage.a = 'aaaaaaaa'; sessionStorage.b = 'b';
在b頁面執行orm
sessionStorage // 輸出 {a: "a", length: 1}
至此,綜合測試一二三,咱們大概能夠獲得這樣的信息:
在a頁面經過window.open(window.location.href)
獲得的b頁面的sessionStorage
會有
a頁面當前sessionStorage
的一份獨立拷貝,此後再改變a頁面的sessionStorage
不會影響到b頁面sessionStorage
;
這時候我又想,若是在a頁面中打開的不是window.location.href
這樣一個地址,而是別的地址,按照咱們對localStorage
和cookie
的瞭解,這裏應該也有域的限制。因此咱們接着測試:
咱們在a頁面(非https://baidu.com
)中打開一個別的域的地址獲得c頁面
window.open('https://baidu.com'); // 獲得c頁面
咱們查看c頁面的sessionStorage
發現並無a頁面sessionStorage
的那些值。恩,這點和咱們認知是同樣的,這個"繼承"也只發生在同域的狀況下。
因此,總結以上,咱們能夠獲得這樣的信息:
在a頁面經過window.open()
打開同域地址獲得的b頁面,b頁面會有a頁面當前sessionStorage
的一份獨立拷貝,這兩個sessionStorage
互不影響。
大概就這麼個結論,那咱們去查看看文檔,看看有沒有文檔提到這個結論。
通過一番搜索我經過這個問題how-to-prevent-sessionstorage-being-inherited-when-using-target-blank-window的答案找到的相應的文檔描述。
When a new Document is created in a browsing context which has a top-level browsing context, the user agent must check to see if that top-level browsing context has a session storage area for that document's origin. If it does, then that is the Document's assigned session storage area. If it does not, a new storage area for that document's origin must be created, and then that is the Document's assigned session storage area. A Document's assigned storage area does not change during the lifetime of a Document.
這是一份html
標準文檔(我理解這應該是給瀏覽器廠商看的實現規範),這裏面有兩個概念須要解釋一下
browsing context
這個概念文檔是這麼解釋的
A browsing contextis the environment in which a browserdisplays aDocument
(normally a tab nowadays, but possibly also a window or a frame within a page).Each browsing context has a specificorigin, host (domain), and port of the URL used to access it. Two objects have the same origin only when the scheme, host, and port all match."), the origin of the active document, and a history that lists all the displayed documents in order.
簡單理解,一個tab
頁、一個frame
就是一個browsing context
。
document's origin
這個文檔也有解釋
Web content's origin is defined by the scheme (protocol), host (domain), and port of the URL used to access it. Two objects have the same origin only when the scheme, host, and port all match.
簡單理解,這就是咱們常說的域。
明白了這兩個概念,再看這段文檔,這和咱們測試得出來的結論是同樣的,更簡單的總結就是:
在a頁面中經過window.open()
打開的同域頁面中會有a頁面當前sessionStorage
的一份獨立拷貝。
這就是這個看起來像sessionStorage
繼承問題的解釋了。固然了這裏的繼承也並非真正的繼承,只是看起來像這麼回事。
在查文檔的過程當中我發現有些老兄想要避免這種繼承
,固然這種避免的方法也是有被人提到的(我的感受不是很優雅),就是在新打開的b頁面load完以後重置一下sessionStorage
,這樣就避免受到上一個頁面的影響了。