后果javascript可以在代码中包含document.write吗?

时间:2017-11-01 15:26:19

标签: javascript html rendering blocking document.write

关于这篇文章的问题是:https://www.html5rocks.com/en/tutorials/speed/script-loading/

他们这样说:

<script src="//other-domain.com/1.js"></script>
<script src="2.js"></script>
  啊,幸福的简单。在这里,浏览器将并行下载两个脚本并尽快执行它们,维护它们的顺序。 “2.js”将在“1.js”执行(或未能执行)之前执行,“1.js”将不执行,直到前一个脚本或样式表执行等等。

     

不幸的是,浏览器会阻止进一步呈现页面,而这一切都在发生。这是因为来自“网络的第一个时代”的DOM API允许将字符串附加到解析器正在咀嚼的内容上,例如document.write。

我的问题是:&#34;浏览器阻止进一步呈现页面,而所有这一切都在发生&#34;。

让我们举个例子:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Test</title>
</head>
<body>
    SOME HTML
    <script>
    document.write( 'bla' );

    // Synchronous delay of 5 seconds
    var timeWhile = new Date().getTime(); 
    while( new Date().getTime() - timeWhile < 5000 );
    </script>
</body>
</html>

我在Firefox和Chrome中对它进行了测试,两个浏览器都在显示&#34;一些HTML&#34; 5秒后!!所以在javascript执行之后而不是在javascript执行之前。

这是什么意思:

  • 在执行内联javascript之前,某些HTML必须位于DOM中,因为它具有同步行为。
  • 当&#34; javascript执行&#34;开始,&#34;一些HTML&#34;还没有完成渲染,因为你无法在屏幕上看到它。
  • 现在&#34; javascript exection&#34;将发生,javascript的执行将阻止渲染。
  • &#34; javascript执行后,&#34;浏览器将完成渲染,它将首次在屏幕上显示一些内容。

在那篇文章中他们说:由于网络的第一个时代&#34;,浏览器将阻止进一步呈现页面。在我看来,这必须是:

  

将进一步阻止&#34;解析HTML&#34;页面

而不是

  

将阻止进一步呈现页面

它不仅仅是关于单词,因为如果您看到它们,您会期望完全不同的东西:&#34;将阻止进一步渲染&#34;。

在我的示例中,在执行javascript&#34;之前,尚未呈现某些HTML。因此,如果它是关于&#34;渲染&#34;而不是直接关于&#34; html解析器&#34;那么document.write会添加(和渲染)&#34; bla&#34;在一些HTML之前。而且我们都知道它没有那样工作。

这部分是正确的:

  

“网络的第一个时代”,允许将字符串附加到解析器正在咀嚼的内容上,例如document.write

但是他们给出的理由不是我认为的:

  

不幸的是,浏览器会阻止进一步呈现页面,而这一切都在发生。这是因为来自“网络的第一个时代”的DOM API

在我的例子中没有理由停止渲染而不显示&#34;某些HTML&#34;已经在执行document.write之前。就像那样,但由于其他原因(反正不是因为document.write)。所以它与&#34;渲染&#34;无关,而是与#34; html解析器&#34;无关。但你不能只看到&#34;渲染&#34;和&#34; html解析&#34;作为相同的事情,并相互替换这些条款。通常html已经存在于DOM中,但在渲染相同的HTML之前,它仍然需要一些时间。

看起来Google始终如一地对待这样的事情。与上面相同,看起来他们在想:前面的HTML是在DOM中,所以让我们说它也已经被渲染了。

实际上我的所有其他帖子也是关于那个(其他情况,但在我看来谷歌的想法一样)。在javascript执行之前,他们不讨论html的渲染(只有在它之后发生的事情)。看起来他们在想:javascript之前的HTML是在DOM中,所以让我们说它也已经被渲染了。在我的帖子中,他们也是#34;令人困惑的渲染&#34;使用&#34; html解析&#34;。在此处查看有关它的更多帖子(如果您对此感兴趣):

Why a browser is not always finishing rendering of the preceding HTML, before executing javascript?

Google is wrong about defer?

Loading external javascript via async script tag at the end of a webpage

Why a browser is not always finishing rendering of the preceding HTML, before executing javascript?

现在你可能正在考虑问题是什么;)。问题是我想听听你的意见:你是否同意我对该文章中的引用的看法。如果没有,请提供一些(好的)论据。

1 个答案:

答案 0 :(得分:0)

我认为引用是正确的,如果不完整的话。渲染确实被阻止了,但不是直接的;渲染依赖于解析器,直到javascript完成执行才解析。所以你是正确的,真正的问题是解析器被阻止,尽管渲染也因为它依赖于解析器而被(间接)阻塞。

在此代码段中,您可以看到第一个div已解析但未呈现;第二个div永远不会在代码段中解析,因为它正在等待javascript完成。

<div id="test1">SOME HTML</div>
<script>
document.write( 'bla' );

var parsedDiv = document.getElementById("test1");
alert(parsedDiv.tagName+": "+parsedDiv.textContent);

// Synchronous delay of 3 seconds
var timeWhile = new Date().getTime(); 
while( new Date().getTime() - timeWhile < 3000 ){
   parsedDiv = document.getElementById("test2");
   if(parsedDiv)alert(parsedDiv.tagName+": "+parsedDiv.textContent);
}
</script>
<div id="test2">SOME MORE HTML</div>