Javascript 加载和执行脚本的顺序
在html页面中包含JavaScript有很多不同的方法。我知道以下选项:Javascript 加载和执行脚本的顺序,javascript,load-order,Javascript,Load Order,在html页面中包含JavaScript有很多不同的方法。我知道以下选项: 内联代码或从外部URI加载 包含在或标记[,] 无、defer或async属性(仅外部脚本) 包含在静态源代码中或由其他脚本动态添加(在不同的解析状态下,使用不同的方法) 不算硬盘上的浏览器脚本、javascript:uri和onEvent-attributes[],已经有16种方法可以执行JS,我肯定我忘了什么 我不太关心快速(并行)加载,我更关心执行顺序(可能取决于加载顺序和时间)是否有一个很好的(跨浏览器)参考
- 内联代码或从外部URI加载
- 包含在或标记[,]
- 无、
或defer
属性(仅外部脚本)async
- 包含在静态源代码中或由其他脚本动态添加(在不同的解析状态下,使用不同的方法)
由于我担心没有,这里是我的具体问题:我有一些(外部)头脚本用于初始化和脚本加载。然后在正文的末尾有两个静态的内联脚本。第一个允许脚本加载器将另一个脚本元素(引用外部js)动态附加到主体中。第二个静态内联脚本希望使用添加的外部脚本中的js。它能否依赖已执行的另一个脚本(以及原因:-)?如果您没有动态加载脚本或将其标记为
延迟
或异步
,则脚本将按照页面中遇到的顺序加载。不管是外部脚本还是内联脚本,它们都是按照在页面中遇到的顺序执行的。外部脚本之后的内联脚本将一直保留,直到之前的所有外部脚本都已加载并运行
异步脚本(无论如何指定为异步)以不可预测的顺序加载和运行。浏览器以并行方式加载它们,并且可以按任意顺序自由运行它们
多个异步对象之间没有可预测的顺序。如果需要一个可预测的顺序,那么必须通过注册异步脚本的加载通知并在加载适当的东西时手动排序javascript调用来编码
动态插入脚本标记时,执行顺序的行为将取决于浏览器。您可以看到Firefox在中的行为。简而言之,Firefox的较新版本默认将动态添加的脚本标记设置为async,除非脚本标记设置为其他
带有async
的脚本标记可以在加载后立即运行。事实上,浏览器可能会暂停解析器的其他操作,并运行该脚本。因此,它几乎可以在任何时候运行。如果脚本被缓存,它可能会立即运行。如果加载脚本需要一段时间,它可能会在解析器完成后运行。使用async
需要记住的一点是,它可以随时运行,而且时间是不可预测的
带有defer
的脚本标记将等待整个解析器完成,然后按照遇到的顺序运行标有defer
的所有脚本。这允许您将相互依赖的多个脚本标记为defer
。它们都将被推迟到文档解析器完成之后,但它们将按照遇到的顺序执行,以保留它们的依赖关系。我认为defer
类似于脚本被放入一个队列中,在解析器完成后将被处理。从技术上讲,浏览器可能随时在后台下载脚本,但在解析器解析页面并解析和运行未标记为defer
或async
的任何内联脚本之前,浏览器不会执行或阻止解析器
下面是那篇文章的一段话:
脚本插入脚本在IE和WebKit中异步执行,但
在Opera和4.0之前的Firefox中同步
HTML5规范(适用于较新的兼容浏览器)的相关部分是。这里有很多关于异步行为的文章。显然,此规范不适用于旧浏览器(或不符合标准的浏览器),您可能需要对其行为进行测试才能确定
引用HTML5规范:
然后,使用以下选项中的第一个选项来描述该情况
必须遵守:
如果元素具有src属性,并且元素具有defer属性
属性,并且元素已标记为“parser inserted”,并且
元素没有异步属性
必须添加元素
到文档创建时将执行的脚本列表的末尾
已完成与该解析器的文档关联的分析
创建了元素
网络任务源在任务队列上放置一次的任务
提取算法已完成,必须设置元素的“准备就绪”
被解析器执行”标志。解析器将处理脚本的执行
如果元素具有src属性,并且元素已被标记
作为“插入解析器”,元素没有异步属性
元素是的文档的挂起的解析阻止脚本
创建元素的解析器。(这种情况只能有一个
每次为每个文档编写脚本。)
网络任务源在任务队列上放置一次的任务
提取算法已完成,必须设置元素的“准备就绪”
被解析器执行”标志。解析器将处理脚本的执行
如果元素没有src属性,并且元素已
标记为“parser inserted”,并且HTML解析器的文档或
创建脚本元素的XML解析器有一个
阻止脚本元素
<script type="module">
import {addTextToBody} from './utils.mjs';
addTextToBody('Modules are pretty cool.');
</script>
<script type="module" src="http://somedomain.com/somescript.mjs">
</script>
// file: test.php
sleep(10);
die("alert('Done!');");
// HTML file:
<script type="text/javascript" src="test.php"></script>
<!DOCTYPE HTML>
<html>
<head>
<title>Test</title>
</head>
<body>
<script type="text/javascript">
var s = document.createElement('script');
s.type = "text/javascript";
s.src = "link.js"; // file contains alert("hello!");
document.body.appendChild(s);
alert("appended");
</script>
<script type="text/javascript">
alert("final");
</script>
</body>
</html>
loadScripts(sources) {
sources.forEach(src => {
var script = document.createElement('script');
script.src = src;
script.async = false; //<-- the important part
document.body.appendChild( script ); //<-- make sure to append to body instead of head
});
}
loadScripts(['/scr/script1.js','src/script2.js'])