从之前我学习的浏览器解析过程中我们知道,浏览器顺序解析,遇到javascript,就会阻塞,并且会执行 javascript, 也会阻塞
我们做一个简单的测试
1 |
|
我加入了一段 google 的连接, :)
肯定不能访问,所以说,浏览器在超时之前下面的所有代码都没有执行,所以我们一般将 script 放在
之前。
1 | <script src="https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwjBkb65gsX_AhXnQPUHHasODVkQFnoECBYQAQ&url=https%3A%2F%2Fcloud.google.com%2Fcdn%3Fhl%3Dzh-cn&usg=AOvVaw3iWKHtZqUXGJwR-4dEGXk8"></script> |
好处是可以有2点
看了这个描述,就开始疑惑, 我们知道加载是异步的,这个我可以理解,那么执行为什么是异步的?
因为在之前的学习当中,主线程解析html,遇到 script 开始加载和执行(交给js引擎),这个过程中是同步的,并且会停止渲染页面。
原因是因为 js引擎和渲染线程是互斥的,js中任何操作dom,css的代码,都可能导致回流或者重绘。
于是我在一段我测试的html中加入了一段代码
1 | <script src="./javascript/test.js" async></script> |
得出了一个结论,加载是异步的,执行是同步的(chatgpt害人啊…)
因为加载的时候并没有影响其他js的执行,然而加载完成立刻开始执行,
1 | 19999999867108864 test.js:7 |
中间这6秒并没有执行其他js代码,于是说明了一切。
再测试一下,是不是先到先得
1 | <script src="./javascript/test.js" async></script> |
复制了一份 test.js 代码, 并且新增了输出,但是一直是 test.js 先执行, 又给 test.js 增加了大量注释,导致他加载速度变慢
1 | -------------test1 start--------------- test1.js:8 1 |
也就是说,网速决定一切,加载完成后立刻执行,先到先得,加载异步,执行同步。
区别:
async 属性表示脚本的加载和执行都是异步的,不会阻塞页面的渲染。脚本加载完成后立即执行,不考虑它们在 HTML 中的顺序,可能会导致脚本之间的依赖关系问题。
defer 属性表示脚本的加载是异步的,不会阻塞页面的渲染,但脚本的执行会在 HTML 页面解析完毕后按顺序执行,可以保持脚本之间的依赖关系。