前言
我就想随便找个地方放东西不行吗?
看别人写的代码,<head>
中写原生js无一例外加了window.onload
, jquery示例中无一例外的加了 $(function(){})
But why? 从此这两尊神秘的大佛让我畏惧了很久,今天写的博文,就是为了崇尚科学破除迷信,撕下’规则’ 的神秘面纱. 而这神秘的面纱,本质就是浏览器加载js的方式
总的来说,浏览器加载js通常就这么几种方式:
阻塞加载
异步加载
延迟加载
阻塞加载
<head>
...
<script src=xx.js ></script>
...
</head>
阻塞加载是浏览器最常见的加载js的方式,不管这条语句出现在页面中的什么位置, 浏览器解析到该标签时, 会堵塞下载(即串行)xx.js, 同时位于该标签之后的资源下载和解析全部挂起. xx.js下载完成之后立刻执行,执行完毕之后,才开始后续资源的下载和解析
异步加载
<script src=xx.js async=”async”></script>
不管这条语句出现在页面中的什么位置, 浏览器解析到该标签时, 会非堵塞下载(即并行)xx.js, (非堵塞下载即该资源在下载的过程中不影响后续资源的下载和解析), 下载完成之后立即执行
延迟加载
<script src=xx.js defer="defer"></script>
不管这条语句出现在页面中的什么位置, 浏览器解析到该标签时, 会非堵塞下载(即并行)xx.js, (非堵塞下载即该资源在下载的过程中不影响后续资源的下载和解析), 下载完成之后挂起,等到DOMContentLoaded
事件完成之后再执行
动态插入Script节点
同异步加载
结语
通过了解了常见的几种加载js的方法,前言中提出的问题相信大家已经有了答案
为什么如果在<head>
中写内联js一般会如此开头:
window.onload=function(){...}
因为$(function(){})是DOMContentLoaded
回调,表示DOM树已经构建完成.window.onload 是整个页面资源加载完成的回调。总而言之,只有先构建了对应的DOM,你才能用脚本去操作它.所以这就是如果在<head>
中写内联js不加window.onload
经常报错的原因,通常因为找不到对应的DOM
这也是我们为什么通常把外链Js放在底部进行加载:
确保了CSS和HTML加载完毕,主要内容已经呈现给用户
确保了CSS和HTML加载完毕,所有DOM处于可操作状态