>说我有这样的代码
<html><body>
<bunch of html tags...>
<script>
function myF()={};
setTimeout(myF, 100);
</script>
<lots of more html goes here.....></body></html>
据我了解,脚本将在解析 html 时进行评估。 但是,在这种情况下,我们有一个 setTimeout,然后是大量的 html 解析。 超时何时可以发出调用? 是否需要等到所有 html 解析完成才能最终调用 myF,还是在发生超时事件时调用 myF,即使有更多的 html 解析要完成?
不,setTimeout() 不一定等待 DOMContentLoaded
如果是这样,我们就不需要DOMContentLoaded
事件了,但如果这还不足以说服你,以下是确凿的证据:
<script>
window.addEventListener('load', function() {
alert("Window Loaded");
});
document.addEventListener('DOMContentLoaded', function() {
alert("DOM Content Loaded");
});
setTimeout(function() {
alert(typeof jQuery == 'function' ? 'jQuery Loaded' : 'jQuery Not Loaded');
}, 15);
</script>
<p>This content will be loaded before jQuery is fetched.</p>
<script>
document.write('<script src="https://code.jquery.com/jquery-3.2.1.min.js?' + Math.random() + '" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></' + 'script>');
</script>
<script>
alert('Loaded after <script src="jquery.min.js">');
</script>
<p>This content will not be loaded until after jQuery is fetched.</p>
如果它必须等待DOMContentLoaded
,你会看到
Loaded after <script src="jquery.min.js">
DOM Content Loaded
Window Loaded
jQuery Loaded
但是(至少对我来说),在相当一部分时间里,输出是
jQuery Not Loaded
Loaded after <script src="jquery.min.js">
DOM Content Loaded
Window Loaded
即使 HTML 的解析是单线程的,但在没有async
的情况下<script>
时也会被阻止,<link>
必须暂停以分别从 URL 获取资源并执行脚本或样式表,这意味着DOMContentLoaded
事件和setTimeout(function() { ... }, 15)
之间存在竞争条件。
不要依赖它。setTimeout
不会创建"中断",它所做的只是将函数添加到浏览器决定检查时检查的队列中。这可能是在线程循环的末尾,也可能是在 HTML 解析期间。
有关 JavaScript 计时器的延伸阅读:https://johnresig.com/blog/how-javascript-timers-work/
等待 HTML 完成解析的更好(标准)方法是这样的:
<html><body>
<bunch of html tags...>
<script>
function myF()={};
document.addEventListener("DOMContentLoaded", myF);
</script>
<lots of more html goes here.....></body></html>
或者,使用 jQuery,如下所示:
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<bunch of html tags...>
<script>
function myF()={};
$(myF);
</script>
<lots of more html goes here.....></body></html>