面试官面前我唯唯诺诺,阿菜面前我重拳出击
从前有座山,山上有座庙,庙里有个小和尚和老和尚,
老和尚问道:"你知道script标签吗?它..."
还没等老和尚问完,小和尚放下手中的木鱼:“师傅,stop,回答完上次for循环和forEach的区别, 你也没让我下山啊,虽然我知道script分为外链引入和内联,我也知道放在body的最后有利于页面的载入”
老和尚连忙制止道:“为师想问你,你知道script上面其实还有defer和async两个属性吗,以及他们的区别”
小和尚拿起无处安放的木鱼并支支吾吾到:"我都把script放到body的尾部, 你还想要人家怎样啦"
老和尚【猝】
HTML中script的那些破事之defer、async
路人甲:“众所周知,script标签上除了经常用到的一个属性src,还有defer、async”;
众人皆摇头
路人甲:“那我直说了, 据史料W3C[1]记载,
- async 规定异步执行脚本(仅适用于外部脚本)。
- defer 规定是否对脚本执行进行延迟,直到页面加载为止。(仅适用外部脚本)“
突然从人群中窜出一位叫阿菜的精神小伙:“口说无凭啊”
众人纷纷随身附和道;
不得已路人甲从口袋里拿出了编辑器和浏览器:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/examp1.js"></script> <!-- console.log('1娃')-->
<script async src="../js/examp2.js"></script> <!-- console.log('2娃')-->
</head>
<body>
<header>
我是header
</header>
<main>
我是主题, 为什么不写div,因为我要语义化
</main>
<footer>
一双脚
</footer>
<script >
document.addEventListener('DOMContentLoaded', function() {
console.log('主体')
})
</script>
<script src="../js/examp3.js"></script> <!-- console.log('3娃')-->
</body>
</html>
结果:
阿菜心想:”你这厮将examp1.js和examp2.js放在head中,不怕遭雷劈吗浏览器解析慢吗?“
常规操作都是将js文件放在body的尾部,不影响document的解析,提升用户体验;
async 不阻塞,但随意插队 ☆☆
❝「async 标签,不阻止document解析,并行加载外部js文件(加载完成后立即执行) 可能在DOMContentLoaded事件前,也可能在后」
❞
<script async src="../js/examp1.js"></script> <!-- console.log('1娃')-->
<script src="../js/examp2.js"></script> <!-- console.log('2娃')-->
看到了吧,除了1娃的位置不确定,其他始终是「2娃 > 主体 > 3娃」
此时如果2娃打不过蛇精,召唤1娃,有可能gg;
这些引入的js文件其中有相互依赖比如:
这种情况的话,有可能报错$.ajax undefined
<script async src="../js/examp1.js"></script> <!-- console.log('1娃')-->
<script async src="../js/examp2.js"></script> <!-- console.log('2娃')-->
这种就更热闹了,就像《西游记》出现孙行者、者行孙、行者孙、奔波灞、霸波奔之类的情况
defer 不阻塞, 排队执行 ☆☆☆☆
❝那这机灵又顽皮的async不可控,那就看看「defer」又能带来怎样的惊喜
❞
- 同样不阻止document解析,同时加载外部js文件
- 不同的是在js文件加载完成之后,并不会立即执行,而是看看自己前后, 按先后顺序执行,且一定是在DOMContentLoaded事件之前执行
<script src="../js/examp1.js"></script> <!-- console.log('1娃')-->
<script defer src="../js/examp2.js"></script> <!-- console.log('2娃')-->
结果:
一个script同时有async、defer, async起作用,defer无效
<script src="../js/examp1.js"></script> <!-- console.log('1娃')-->
<script defer async src="../js/examp2.js"></script> <!-- console.log('2娃')-->
结果:
内联的script标签想用async、defer, 没门
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/examp1.js"></script> <!-- console.log('1娃')-->
<script src="../js/examp2.js"></script> <!-- console.log('2娃')-->
<script async>
console.log('内联async')
</script>
</head>
没有效果的,defer也没有效果,
❝众人如梦初醒,路人甲捋了捋自己那不存在的胡子并露出满意的笑容,只见那位远去少年的身影说声:“放到body底部不香吗?” 菜终究是菜啊!
❞
回头看
- async、defer都不会阻塞document的解析,
- defer加载完成,会在按js文件引入顺序执行,且在DOMContentLoaded之前
- async加载完成,立即执行,不管这个DOMContentLoaded,在前在后都有可能
❝ ❞
Reference
[1]W3school: HTMLScript标签。
本文使用 mdnice 排版