【问题标题】:<script defer> and $(document).ready<script defer> 和 $(document).ready
【发布时间】:2012-01-28 03:23:38
【问题描述】:

根据http://caniuse.com/script-defer,大部分浏览器都支持script标签的defer属性。

我想知道&lt;script defer src="..."&gt; 指定的脚本是在jQuery 的$(document).ready() 之前还是之后执行的?主要的现代浏览器(Chrome、Firefox、IE 等)在执行顺序上是一致的还是有所不同?

【问题讨论】:

    标签: javascript jquery html


    【解决方案1】:

    基于这个 fiddle 我不得不说 jQuery 的 $(document).ready() 使用 defer 声明的脚本之后执行。我用 Firefox 和 Chrome 对其进行了测试,两者都具有相同的行为,不受脚本顺序的影响。

    我猜其他浏览器上的行为可能会根据它们的实现而改变,所以它总是不确定的。

    编辑:事实证明,defer 属性应该与外部 javascript 文件一起使用。我编辑了小提琴以显示这一点,显然结果相同。

    在此处更新小提琴:http://jsfiddle.net/RNEZH/15/

    【讨论】:

    • Opera 中的结果相同,但 defer 属性不是只对外部脚本感兴趣吗?我认为 没有意义。
    • @TomS: spec 说“如果 src 属性不存在,则不得指定 defer 和 async 属性。”这是关于是否继续解析文档,而不是等待执行。
    • 我在 IE6 中使用你的小提琴得到了相同的结果,所以 IE6+ 也应该可以工作。
    • 这假设你已经推迟了 jQuery,对吧?我认为小提琴做了一个同步的 jQuery 加载,然后是你的延迟,ready()。
    • 我会在今天之前同意你的看法,但我发现如果你向脚本添加延迟(例如使用 fiddler 使脚本需要 2 秒)jquery 就绪事件在延迟脚本加载之前发生(仅在 Chrome 上测试)。看来您可以使用$(window).on("load", initFunc),它将在延迟脚本之后运行initFunc。不幸的是,这并不理想,因为我相信加载图像后会触发加载事件窗口等...
    【解决方案2】:

    defer 属性有一个很好的write-up and analysis另外请参阅帖子中的 cmets,了解有关如何在 HTML5 中重新定义 defer 的更多信息。

    我的结论:defer 过于依赖浏览器,无法指望。因此,请使用 jQuery 文档就绪技术。

    换一种说法,jQuery 的一个重要原因是为了覆盖浏览器的不一致性。延迟是另一种这样的不一致,对于编写良好的页面应该避免。

    【讨论】:

    • 我在任何地方都看不到任何关于如何在 HTML5 中重新定义 defer 的信息。
    【解决方案3】:

    简单地说,script 应该在$(document).ready() 之前执行,不管defer 是否被使用,几乎所有主流浏览器都是supportdefer

    但为了安全起见,我鼓励您同时使用$(document).ready()defer。 那么为什么defer?因为它有助于页面快速显示(因为外部脚本是并行加载的)并且是 Google 页面速度工具中一个非常重要的因素,所以可以在这里找到一个很好的细节http://code.google.com/speed/page-speed/docs/payload.html#DeferLoadingJS

    【讨论】:

    • 此信息不正确,即使尚未加载带有 defer 参数的 jquery,也会调用文档就绪
    【解决方案4】:

    要延迟内联 javscript,您可以使用 type="module" ,这会使 $(document).ready() 变得多余。

    <script type="module">alert('defered inline js')</script>
    

    因为 type="module" 意味着延迟脚本将与其他延迟脚本一起执行。

    看看我能否在 2020 年 9 月使用 92% 的浏览器支持。 https://caniuse.com/es6-module

    【讨论】:

      【解决方案5】:

      我在 Chrome (88.0.4324.96) 上的 jQuery 3.0 之前的版本中观察到了竞争情况。我在 Safari 和 Firefox 上都看不到这个。

      <body>
        <script defer src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
        <script defer src="test.js"></script>
      </body>
      

      test.js:

      
      jQuery(document).ready(function ($) {
        console.log('jQuery version', $().jquery);
        console.log(a);
      });
      
      const a = 'OK';
      

      根据我的经验,Cannot access 'a' before initialization 失败的概率约为 10%。

      一旦我升级到 jQuery 3,我就无法重现。由于这是一个竞争条件,我不能 100% 确定,但对我来说似乎很有定论。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-26
        • 2015-12-10
        • 2023-03-14
        相关资源
        最近更新 更多