1. JavaScript放在head和body的区别
-
- 在HTML head部分中的JavaScripts会在被调用的时候才执行。
- 在HTML body部分中的JavaScripts会在页面加载的时候被执行。
-
- head 部分中的脚本: 需调用才执行的脚本或事件触发执行的脚本放在HTML的head部分中。当你把脚本放在head部分中时,可以保证脚本在任何调用之前被加载。
- body 部分中的脚本: 当页面被加载时执行的脚本放在HTML的body部分。放在body部分的脚本通常被用来生成页面的内容。
- 个人理解:
- 类似函数、全局变量的可以在head中给出。
- 和页面相关的js,或者需要在页面加载之后再利用js进行操作的js,可以放在body中加载。
- 参考自:JavaScript放在head和body的区别
2. js文件加载的阻塞
-
在浏览器解析
html
的时候,解析到script
标签,会去请求这个js
文件,此时会阻塞整个页面的加载。
在加载完成之后,会解析该js
文件,此时页面仍被阻塞。
在js
解析执行完成之后,才会继续解析页面。 -
可以使用alert模拟一下阻塞。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>alert模拟加载js阻塞</title> <script> alert("正在加载-js---") </script> <style> #test{ width: 100px; height: 100px; background-color: azure; } </style> </head> <body> <div id="test"></div> </body> </html>
可以看到,在
alert
的时候,页面并没有显示出test
元素,在alert
结束之后才显示出test
元素。
可见,浏览器在解析script
,执行到alert
的时候,对html
的解析阻塞了。
所以有时候将js
文件放在body
的结尾,可以防止js
的加载执行阻塞到页面的加载,避免页面空白带来不佳的用户体验。 -
解决方式
- 将
js
代码放在最后 - 在
script
标签中添加defer
- 在
script
标签中添加async
解释:
defer
: 规定是否对脚本执行进行延迟,直到页面加载为止。async
: 规定异步执行脚本(仅适用于外部脚本)。defer
示例:可以看到在浏览器中,先显示出了test
元素,然后弹出了提示框。<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>js放在head和body的区别</title> <script src="3_js放在head和body的区别.js" defer="defer"></script> <style> #test{ width: 100px; height: 100px; background-color: azure; } </style> </head> <body> <div id="test"></div> </body> </html>
async
示例:假设body
内元素很多。
可以发现,在加载到test
元素之前,浏览器一边解析html
,一边执行加载进来的js
。
在js
被完全加载之后,浏览器阻塞html
解析,开始执行js
。
在js
执行完成之后,继续解析html
。<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>js放在head和body的区别</title> <script src="3_js放在head和body的区别.js" async="async"></script> <style> #test{ width: 100px; height: 100px; background-color: red; } </style> </head> <body> <script> // 模拟加载body里面的元素,假设元素很多 for(let i = 0; i < 1000; i++){ } </script> <div id="test"></div> </body> </html>
- 将
-
参考:浏览器渲染页面和加载页面机制
参考:js和css的加载造成阻塞
参考:JS加载阻塞HTML的解析