李宗辉

John Lee

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

 前言

      HTML中的<script>标签大家都是知道的,嗯,是的,最常见的标签了。这个标签有一个defer属性,本文就来探讨一下HTML中<script>标签的defer属性,不管应用、笔试或者面试时,希望我们都能很好的面对这个defer属性。这里谈谈HTML中<script>标签的defer属性延迟脚本与load事件注册程序执行的先后问题。当然此文是从全面理解defer属性入手分析的。

一、script标签defer属性定义

     要理解一个元素的属性,当然最权威的就是了解其官方定义喽,因此,关于<script>标签的defer属性,就从其定义开始介绍喽。

     <script>标签的defer属性表示脚本可以延迟到文档完全被解析和显示后再执行。只对外部脚本有效。且是一个可选的属性。

     <script>标签有6个属性哦,defer属性是其中的一个。详细定义可以在互联网上查到呢。给个链接方便查询喽:http://www.w3school.com.cn/tags/att_script_defer.asp

    关于<script>标签defer属性定义差不多就是这样描述的啦,要怎么理解红色字体给出的<script>标签defer属性的定义呢?相信理论结合实例是最好的理解方式呢。

二、script标签defer属性的理解

    从定义中可以得出以下的信息喽:

  1.     该属性只应用于对外部js脚本的引用时。
  2.     是可以有可以没有的,当然,如果没有使用defer属性,就不会对外部脚本应用这个属性的功能喽,@_@~貌似是废话呢。
  3.     defer属性的功能是延迟脚本的执行,注意这里是执行哦,不是加载呢。
  4.     外部脚本延迟到什么时间执行呢?定义中给出的信息是文档完全被解析和显示哦。

    差不多就是读出这些信息吧,我们就来一个个的理解喽。

    第1点和第2点都很明了啦,就不多说了,先分析第4点吧,就是defer属性要延迟外部js脚本的执行,那是要等到什么时候才开始执行外部脚本呢?定义中说是要等到文档完全被解析和执行后。文档完全被解析和执行后,何为文档完全被解析和执行后呢?关于HTML文档,首先要加载,然后浏览器解析HTML标签,然后渲染,加载过程中遇到脚本则执行脚本,此时的脚本当然是没有被延迟执行喽。我们知道浏览器在对HTML文档的处理过程中,有一个默认的原则是“自上而下,自左而右”,相信关于这个原则大家是没有什么疑问的。由此就可以解释文档完全被解析和显示是什么含义:也就是说喽,浏览器处理一个HTML文档,是自上而下自左而右地加载,边加载边解析(解析就是将HTML标签语言解释成相应的显示效果喽),最后页面完全被显示出来后,执行被延迟的脚本。说了这么多,文档完全被解析和显示可以认为是文档被加载,解析显示后这个时间点。

    这些都没有什么疑问,但是我们给load事件注册事件处理程序,load事件处理程序触发执行的时间也是页面完全加载后执行的呢。因为load事件的触发事件就是页面完全加载完毕喽。那么此时HTML文档中<script>标签中使用了defer属性来延迟执行脚本,延迟执行的脚本执行事件也是页面加载解析完毕后呢,那这两个中的代码谁先执行呢。通过下面的代码可以验证:

 

<html>
    <head>
         <script type="text/javascript" src="test.js" defer="defer"></script>
    </head>
    <body>

         ....

         <script type="text/javascript">
                window.onload = function(){
                     alert("A");
                }
         </script>
    </body>
</html>

 

以上代码中“test.js”中的代码是“alert("B");”,在火狐和IE9下测试的结果是先弹出“B”,后弹出“A”。这就证明了:当页面中有load事件处理程序,又有defer延迟脚本时,首先执行的是defer延迟脚本。也就是说,页面加载解析完毕后,立即执行defer延迟脚本,然后再执行load事件注册程序。

    原因分析:谈一下自己的想法吧,首先先介绍完defer属性的理解,上面只是介绍了从定义中得出的4个信息的第4个点,第3点还没有说呢。defer属性的功能是延迟脚本的执行,但是并没有延迟脚本的加载,当浏览器解析到:

<script type="text/javascript" src="test.js" defer="defer"></script>
    

 

这段代码的时候,执行的动作是:立即加载,延迟执行。也就是说浏览器执行到这段代码的时候,已经将这段代码加载完毕,只是延迟执行而已。那么现在解释下为什么defer延迟脚本会早于load事件注册程序执行喽,因为defer脚本程序已经加载过,是属于页面中的一部分喽,而load事件指的是页面完全加载完毕才会触发的哦。希望这样能好理解些。

三、关于HTML中<script>标签的defer属性的补充

      当页面脚本中出现:

 

 <script type="text/javascript" defer="defer" src="example1.js"></script>
<script type="text/javascript" defer="defer" src="example2.js"></script>

时:HTML5规范要求脚本按照他们出现的先后顺序执行,因此第一个延迟执行脚本会先于第二个延迟执行脚本执行,并且需要注意的是这两个脚本会先于DOMContentLoaded事件执行,也就是load事件喽。这是HTML5中的规范。现在的执行情况是,延迟执行脚本并不一定会按照顺序执行,也不一定会在DOMContentLoaded事件执行触发前执行。HTML5还规范了defer属性只适用于外部脚本文件。IE4~IE7还支持对嵌入脚本的defer属性。IE8之后是支持HTML5规范的行为的。

      掌握一个知识在于应用,在于表达,做到确实不易呀。欢迎指正~

   

 

 

 

 

 

    

     

 

 

 

 

 

 

 

 

posted on 2012-09-13 17:22  李宗辉  阅读(2322)  评论(0编辑  收藏  举报