我已经遇到了一个小烦恼,这是一个巨大的问题。关闭窗口中断事件循环假设
问题1:在Internet Explorer中,当你关闭一个窗口(如果您通过window.open
打开)的ownerDocument
将随之消失。
这意味着任何对DOM的调用(例如appendChild
或createElement
)都将失败,产生SCRIPT70: Permission Denied
或SCRIPT1717: The interface is unknown
。
我看过其他浏览器(如Chrome)的行为。在Chrome中,ownerDocument
仍引用#document
,但ownerDocument.defaultView
最终将为undefined
。这对我有意义。致电appendChild
和createElement
将通过。我认为一切都很好,只要你不直接引用defaultView
即可。
问题2:在Internet Explorer中,当您点击产生的窗口的关闭按钮时,它似乎不遵守Event循环。我附加了一个unload
事件到生成的窗口,它立即触发,而不是在事件循环结束时排队。这是而不是对我有意义。处理这个相当微不足道的问题变得不可能。
如果我们只是有问题1会有-still痛苦但是 - 简单的解决办法:检查ownerDocument
存在,如果不跳。因为它是ownerDocument
在同步JavaScript代码中消失。
预期行为:如果您已经参考了DOM节点,垃圾收集的完整性应该不会消失。
预期行为2: DOM节点不应该在同步代码中消失。 (除非你删除它当然)。
已知的解决方法:将与DOM交互的所有代码移动到窗口中,以便当窗口关闭时以及JavaScript运行时环境关闭。这不是一个简单的解决方案,可能需要对体系结构进行重大更改。
蹩脚的解决方案:在功能中包含与DOM进行交互的任何函数,如果该函数检测到元素的窗口已关闭,将会消耗错误。这是非常有创意的,并且对性能有重大影响,IE已经非常缓慢。
有没有更好的解决方案?
我至少想要的是忽略任何Error
的方式,因为用户关闭了一个窗口。 问题1和问题2打破了JavaScript代码的基本假设:垃圾回收和事件循环。
演示脚本
<script type="text/javascript">
function go() {
var popup = window.open('', 'open', 'width=500,height=300,scrollbars=yes,resizable=yes');
popup.document.open();
popup.document.write('<html><head></head><body></body></html>');
popup.document.close();
for (var i = 0; i < 10000; i += 1) {
var node = popup.document.createTextNode(i + " ");
popup.document.body.appendChild(node);
}
}
</script>
<input type="button" onclick="go();" value="Open popup" />
(保存为.html文件)
说明:
- 打开Internet Explorer 9中
- 点击 “打开弹出”
- 关闭窗口,而它的渲染
- 观察“权限被拒绝”
这是一个的jsfiddle:http://jsfiddle.net/C9p2R/1/
这是否发生在所有IE版本中? – 2013-02-15 13:34:21
它发生在IE9中。我不敢测试旧版本。我不知道IE10。 – Halcyon 2013-02-15 13:34:49
我是否明白,只要您持有对其的引用,Chrome就可以修改关闭窗口的DOM?你想在IE中的行为? – Bergi 2013-02-15 13:58:48