前言
JavaScript是浏览器的内置脚本语言。当网页中嵌入了JavaScript脚本,浏览器加载网页时,就会执行脚本,从而操作浏览器,实现各种动态效果
JavaScript代码嵌入网页的方法
1、<script>
元素直接嵌入代码
<script type="text/javascript">
function sayHello() {
alert("hello!");
}
</script>
2、<script>
元素加载外部脚本
<script type="text/javascript" src="example.js"></script>
<script>
标签相关属性
type属性
-
<script>
标签默认就是JavaScript代码,嵌入javascript脚本时,type属性可以省略 - 如果type属性的值,浏览器不认识,就不会执行其中的代码,所以可以在
<script>
标签中嵌入任意的文本内容,只要加上一个浏览器不认识的type属性就行,浏览器不会执行也不会显示它的内容,但是这个<script>
节点依然存在于DOM之中,可以使用<script>
节点的text属性读取它的内容
defer属性
<script src="a.js" defer></script>
<script src="b.js" defer></script>
defer属性的运行流程:
- 浏览器开始解析HTML网页
- 解析过程中,发现带有defer属性的
<script>
元素 - 浏览器继续往下解析HTML网页,同时并行下载
<script>
元素加载的外部脚本 - 浏览器完成解析HTML网页,此时再回过头执行已经下载完成的脚本
需要注意:
- 异步加载资源
- 按照顺序执行脚本
- 使用defer加载的外部脚本不应该使用document.write方法
async属性
<script src="a.js" async></script>
<script src="b.js" async></script>
async属性的运行流程:
- 浏览器开始解析HTML网页
- 解析过程中,发现带有async属性的
<script>
标签 - 浏览器继续往下解析HTML网页,同时并行下载
<script>
标签中的外部脚本 - 脚本下载完成,浏览器暂停解析HTML网页,开始执行下载的脚本
- 脚本执行完毕,浏览器恢复解析HTML网页
需要注意:
- 异步加载资源
- 并不会按照顺序执行JS,谁先下载完,谁就先执行
- 使用async加载的外部脚本不应该使用document.write方法
async和defer属性归纳
- 都能解决“阻塞效应”
- 都是异步加载资源,但执行顺序不一样
- 如果脚本之间没有依赖关系,就使用async属性,如果脚本之间有依赖关系,就使用defer属性
Load事件
- 浏览器已经加载了所有依赖的资源,包括图片样式表等
- 可以在load事件触发时获得图片的大小
- 绑定到window,
window.addEventListener("load",ready);
DOMContentLoaded事件
- 浏览器已经完全加载了HTML,DOM树已经构建完毕
- JS可以访问所有DOM节点,但是图片和样式表等外部资源可能没有下载完毕
- 绑定到document:
document.addEventListener("DOMContentLoaded",ready);
涉及到async的知识点
- 异步async脚本一定会在页面load事件之前执行
- 异步async脚本可能会在DOMContentLoaded事件触发之前或者之后执行
动态生成脚本
['a.js', 'b.js'].forEach(src => {
const script = document.createElement('script');
script.src = src;
script.async = false;
document.head.appendChild(script);
});
- 不会阻塞页面渲染
- async设置为false可以保证b.js在a.js后面执行
- 在这段代码后面加载的脚本文件,会等在b.ja执行完成后再执行
相关知识点总结
- 包含在
<script>
标签内部的JavaScript代码,将被从上到下一次解析 - 无论以哪种方式嵌入代码,只要不存在defer和async属性,浏览器都会按照
<Script>
标签在页面中出现的先后顺序对它们进行解析 - 加载外部脚本的优点:可维护性、可缓存、适应未来
-
<script>
放在底部的原因1、避免“阻塞效应”。2、避免,在DOM结构生成之前调用DOM节点,而产生错误