天天看点

document.write什么时候会清除文档内容?

在调用document.write时,会将内容写入文档流,所以会自动调用document.open方法打开文档流,如果文档流已经关闭,则会清除所有内容。

那什么时候代表文档流已经关闭呢?即所有的内容都已经读入到浏览器中(含所有的内联CSS、HTML标签),即页面的主线程没有执行完成,也就是我们所看到的源代码里面的所有内容。

以如下的代码为例:

<body>
    <h1>Hello, World!</h1>
    <script type="text/javascript">
        document.write('<h2>Hello, Yiifaa!</h2>')
    </script>
</body>
           

因为此时页面的主线程没有执行完成,所以会将“

Hello, Yiifaa!

”添加到文档末尾,但如果利用setTimeout暂时放弃主线程的执行,切换到任务队列中,那么随着文档流的写入结束,此时需要重新打开文档流,那么文档的内容则会全部覆盖,如下:

<body>
    <h1>Hello, World!</h1>
    <script type="text/javascript">
        //  暂时放弃主线程的执行
        setTimeout(function() {
            document.write('<h2>Hello, Yiifaa!</h2>')
        }, );
    </script>
</body>
           

通过上面的例子可以看出,只要浏览器解析到文档末尾,则浏览器主线程结束,文档流关闭。

需要特别指出的,文档是严格按照从下直下的顺序执行的,即使某一个js由于网络原因延迟了较长时间,那么文档也会一直等待它的执行,直到超时或等待的JS执行完成,从而将浏览器主线程的执行周期拉长。

模拟JS延时的代码如下(jsp实现):

<%@ page language="java" contentType="text/javascript; charset=UTF-8" pageEncoding="UTF-8"%>
<%
    Thread.sleep();
%>
//  业务处理代码
alert('defered script!');
           

顺带说一个document.write产生的安全现象,如果在document.write写入的内容请求了其他的JS文件,会提示跨站脚本攻击:

A Parser-blocking, cross site (i.e. different eTLD+) script,
http://localhost/mirana-birt/defered.jsp, is invoked via document.write. 
The network request for this script MAY be blocked by the browser in this or a future page load due to poor network connectivity. If blocked in this page load, it will be confirmed in a subsequent console message.
           

示例代码如下:

document.write('<script src="http://localhost/mirana-birt/defered.jsp"><\/script>')
setTimeout(function() {
    document.write('<h2>Hello, Yiifaa!</h2>')
}, )
           

更有意思的是,IE浏览器与Chrome表现出截然不同的表现,IE会直接抹掉所有内容,并会取消所有未完成的请求。

另,在文档流的写入过程,由于JS单线程的限制,document.close()并不能真正关闭流,只能起到一个代码标记的作用,如下面的代码,并不会清除文档内容,说明文档流并没有关闭:

<body>
    <h1>Hello, World!</h1>
    <script type="text/javascript">

        document.close()
        document.write('Hello, Yiifaa!')
    </script>
 </body>
           

结论

document.write的写入效果跟文档流所处的状态严格相关,如果文档流已关闭,则必然会出现清除文档内容的现状。

继续阅读