通过js动态插入的script元素的代码执行时机
tanhui 12/20/2021
html
通过js动态插入的script元素的代码执行时机
先说结论:
如果是在加载页面的过程中通过js动态插入的script元素,无论其元素位置在哪儿,都会在其资源加载完毕后立即执行(如果是直接写在script标签内的代码文本,则会在添加到document中时立即执行,如果通过src加载远程资源, 其资源请求顺序会被放在所有静态dom节点的资源请求顺序之后,并在资源下载完毕后立即执行),同时不会阻塞html的解析过程
证明1
demo/1.js
动态的插入script标签加载 demo/3.js
console.log('1 loaded');
const script = document.createElement('script');
script.src = 'demo/3.js';
script.type = 'text/javascript';
document.head.appendChild(script); // 插入到head元素的尾部
1
2
3
4
5
2
3
4
5
demo/2.js
console.log('2 loaded');
1
demo/3.js
const p = document.querySelector('p')
console.log(p) // 打印p元素
console.log('3 loaded');
1
2
3
2
3
html:
注: http://127.0.0.1:8090会延迟3秒然后响应,并输出 server loaded,这里将其称作延时script。
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="demo/1.js"></script>
<script src="http://127.0.0.1:8090"></script>
<title>Document</title>
</head>
<body>
<p>其实我很好</p>
<script src="demo/2.js"></script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
输出如下:
network面板如下:
可以看出,即便将script元素添加到尾部,且上面的延时script还未加载完毕,这个动态添加的script元素也在其资源加载完毕后便执行了代码。而且因为此时延时script阻塞了dom解析构建,所以未能找到p元素。
证明2
将html稍微改动下,http://127.0.0.1:8090服务也取消延时,改为立即响应:
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="demo/1.js"></script>
<script src="demo/2.js"></script>
<title>Document</title>
</head>
<body>
<p>其实我很好</p>
<script src="http://127.0.0.1:8090"></script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
输出如下:
network面板:
可以看出,在执行3.js的时候已经完成了首次渲染,因为已经可以打印出p元素,所以动态加载的script标签并不会阻塞dom构建。
证明3
如果使用内联代码又是怎样的顺序呢?
将 demo/1.js 代码修改, 动态添加的script标签直接使用内联代码
console.log('1 loaded');
const script = document.createElement('script');
script.innerText="console.log(document.querySelector('p'));console.log('3 loaded')";
script.type = 'text/javascript';
document.head.appendChild(script); // 添加到head的尾部
1
2
3
4
5
2
3
4
5
html:
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="demo/1.js"></script>
<script>
console.log('2 loaded')
</script>
<title>Document</title>
</head>
<body>
<p>其实我很好</p>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
输出:
可以看到, 3 loaded 输出在 2 loaded之前,说明script元素被添加到head元素中就立即执行了。