script上defer及async属性浅谈

2019-11-13  本文已影响0人  该帐号已被查封_才怪

当script上有defer或async属性时,script的下载均不会阻塞html的解析,但是一旦含有async属性的脚本被下载完,它就会立即执行(执行时会阻塞html的解析),而含有defer属性的脚本则是在html解析完后(DOMContentLoaded触发前)才执行;没有defer或async属性的脚本在下载时会阻塞html的解析,一旦其下载完它还会继续阻塞html的解析;具体可见下图:


image.png

图片来源 https://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html

拿个超简单的页面测试一下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
  <meta content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0,user-scalable=no" name="viewport">
   <title>Title</title>
  <script src="js/defer.js" defer></script>
  <script src="js/no.js"></script>
  <script src="js/async.js" async></script>

</head>
<body>
<div class="cainiao">测试script上defer及async属性</div>

<!--<script type="text/javascript">-->
<!--alert(str);//因为没有定义str,所以浏览器会出错,下面的不能运行-->
<!--alert("我是代码块一");//没有运行到这里-->
<!--var test = "我是代码块一变量";-->
<!--</script>-->
<!--<script type="text/javascript">-->
<!--alert("我是代码块二"); //这里有运行到-->
<!--alert(test);-->
<!--</script>-->

</body>
</html>

image.png

结果你可能觉得有点出乎意外,为什么defer会比async先执行?不是defer等到html解析完后才执行的吗?为什么它比async先执行? 其实仔细想想,defer是在html解析完后(DOMContentLoaded事件前)执行的,由于测试的页面比较简单,因此可能DOMContentLoaded事件完成后,async的脚本才下载完,所以async才被执行;当然这只是我们的分析,我们可以拿各个阶段的时间对比一下;接下来,我们来通过js获取相应的时间戳来验证这个想法:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
  <meta content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0,user-scalable=no" name="viewport">
   <title>Title</title>
  <script>
    window.addEventListener('DOMContentLoaded',function () {
      console.log('DOMContentLoaded的时间戳是'+new Date().getTime())
    })
    function getAsyncLoadTime() {
      console.log('async load的时间戳是'+new Date().getTime())

    }
  </script>

  <script src="js/defer.js" defer></script>
  <script src="js/no.js"></script>
  <script src="js/async.js" async onload="getAsyncLoadTime()"></script>
</head>
<body>
<div class="cainiao">测试script上defer及async属性</div>

<!--<script type="text/javascript">-->
<!--alert(str);//因为没有定义str,所以浏览器会出错,下面的不能运行-->
<!--alert("我是代码块一");//没有运行到这里-->
<!--var test = "我是代码块一变量";-->
<!--</script>-->
<!--<script type="text/javascript">-->
<!--alert("我是代码块二"); //这里有运行到-->
<!--alert(test);-->
<!--</script>-->

</body>
</html>

image.png

上面的测试数据验证了我们的想法, 我后来刷新很多次,极少数也会出现下面的结果


image.png

拿个复杂一点的页面测试一下:

image.png

补充知识

1、JavaScript 的性能优化:加载和执行
2、你真的了解script标签吗?

上一篇 下一篇

猜你喜欢

热点阅读