script标签中的defer属性
html
4.0.1为<script>
标签增加了defer属性,书中说IE4-7还支持嵌入式脚本的defer属性,经测试发现IE8-9也支持,并不是书上说的完全支持html5
规定的行为,所以defer属性最佳实践还是用在引用外部script
文件时使用,而且这些外部脚本文件最好是不影响页面结构的,否则使用defer的意义就不大了
测试
高级编程第三版一书中,这样说到:
在现实当中,延迟脚本并不一定会按照顺序执行,也不一定会在DOMContentLoaded事件触发前执行,因此最好只包含一个延迟脚本
测试代码:
<body>
<script src="../static/js/angularjs.js"></script>
<script defer src="../static/js/animate.js"></script>
<script src="../static/js/angularjs.loader.js"></script>
<script defer src="../static/js/angularjs.cookie.js"></script>
<script src="../static/js/angularjs.message.js"></script>
<script defer src="../static/js/angularjs.resource.js"></script>
<script defer>
console.log("defer js");
</script>
<script>
console.log("not defer js")
</script>
</body>
加载结果:
chrome(63)
angularjs.js:34256 angularjs is loaded!
angularjs.loader.js:609 angularjs.loader.js is loaded!
angularjs.message.js:742 angularjs.message.js is loaded!
(index):16 defer js
(index):19 not defer js
animate.js:4159 animate.js is loaded!
angularjs.cookie.js:327 angularjs.cookie.js is loaded!
angularjs.resource.js:858 angularjs.resource.js is loaded!
IE9
日志: angularjs is loaded!
日志: angularjs.loader.js is loaded!
日志: angularjs.message.js is loaded!
日志: not defer js
日志: animate.js is loaded!
日志: angularjs.cookie.js is loaded!
日志: angularjs.resource.js is loaded!
日志: defer js
经过测试发现,在chrome下,html
文档内嵌的脚本不支持defer属性,而且加了defer属性的外部脚本文件都是按照顺序加载的,而在IE9下,html
文档内嵌的脚本仍然支持defer属性,而加了defer属性的外部脚本文件也是按照顺序加载!
测试代码:
<html>
<head>
<link href="https://cdn.bootcss.com/bootstrap/4.0.0-beta.3/css/bootstrap.css" />
</head>
<body>
<script type="text/javascript" defer="defer" src="../static/js/11.js"></script>
<script type="text/javascript" defer="defer" src="../static/js/jq.js"></script>
<script type="text/javascript" defer="defer" src="../static/js/12.js"></script>
<script type="text/javascript" defer="defer" src="../static/js/13.js"></script>
<script type="text/javascript" defer="defer" src="../static/js/14.js"></script>
<script type="text/javascript" defer="defer" src="../static/js/15.js"></script>
<script type="text/javascript" defer="defer" src="../static/js/1.js"></script>
<script type="text/javascript" defer="defer" src="../static/js/2.js"></script>
<script type="text/javascript" defer="defer" src="../static/js/3.js"></script>
<script type="text/javascript" src="../static/js/4.js"></script>
<script type="text/javascript" defer="defer" src="../static/js/5.js"></script>
<script defer="defer">
console.log("defer!!!!!!!!!!!!!!!!!!");
document.addEventListener("DOMContentLoaded", function(){
console.log("Domcontent loaded")
})
window.onload=function(){console.log("window is onload")}
</script>
<script>
console.log("no defer no defer")
</script>
</body>
</html>
加载结果:
IE9
4.js loaded
no defer no defer
11.js loaded
12.js loaded
13.js loaded
14.js loaded
15.js loaded
1.js loaded
2.js loaded
3.js loaded
5.js loaded
defer!!!!!!!!!!!!!!!!!!
jq loaded
Domcontent loaded
window is onload
chrome(63)
4.js loaded
(index):19 defer!!!!!!!!!!!!!!!!!!
(index):26 no defer no defer
11.js:1 11.js loaded
jq.js:6 jq loaded
12.js:1 12.js loaded
13.js:1 13.js loaded
14.js:32898 14.js loaded
15.js:1 15.js loaded
1.js:32896 1.js loaded
2.js:32896 2.js loaded
3.js:32896 3.js loaded
5.js:32896 5.js loaded
(index):21 Domcontent loaded
(index):23 window is onload
firefox(57)
4.js loaded
defer!!!!!!!!!!!!!!!!!!
no defer no defer
11.js loaded
jq loaded
12.js loaded
13.js loaded
14.js loaded
15.js loaded
1.js loaded
2.js loaded
3.js loaded
5.js loaded
Domcontent loaded
window is onload
经过测试发现,在chrome下,html
文档内嵌的脚本不支持defer属性,而且加了defer属性的外部脚本文件都是按照顺序加载的,firefox的表现和chrome一样,而在IE9下,html
文档内嵌的脚本仍然支持defer属性,而加了defer属性的外部脚本文件不一定按照顺序加载!
总结
虽然这个测试不能覆盖所有的情况,但是了解到了一点,这个defer属性的表现情况不容乐观,尤其是在IE下,经过测试,发现IE6-9(更低的版本未测试)下表现一致,支持内嵌defer和外部引用defer,加载顺序不是按照书写顺序来的,而在高版本的chrome和firefox下,都是只支持外部引用脚本的defer,脚本文件的加载顺序和书写顺序是一致的(测试文件数量较小,暂未出现顺序不一致的情况),所以最好的选择是:将要设置defer属性的外部脚本文件放在<body>
标签之前,内容元素之后且不加defer属性