浅谈sessionStorage的"继承"问题

问题复现

最近在写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这样一个地址,而是别的地址,按照咱们对localStoragecookie的了解,这里应该也有域的限制。因此咱们接着测试:

测试四

咱们在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 a Document(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,这样就避免受到上一个页面的影响了。

参考文档

相关文章
相关标签/搜索