jQuery:如果外部JS在页面底部,为什么要使用document.ready?

90

我将所有的JS代码都作为外部文件包含在页面底部。在这些文件中,我定义了一些方法,如下所示,并从ready事件中调用它们:

var SomeNamepsace = {};

SomeNamepsace.firstMethod = function () {
    // do something
};

SomeNamepsace.secondMethod = function () {
    // do something else
};

$(document).ready(function () {
    SomeNamepsace.firstMethod();
    SomeNamepsace.secondMethod();
});

然而,当我移除ready函数并直接调用方法时,一切仍然正常,但是执行速度显著加快——在一个相当基本的文件上快了将近一秒钟!由于文档此时应该已经加载完毕(因为所有标记都在脚本标签之前),是否还有充分的理由使用ready事件?


9
有趣的问题。不幸的是,目前的答案并没有真正回答这个问题,而我也没有任何好的答案。也许重新表述这个问题会有所帮助:“将 JavaScript 文档放在文件末尾是否保证在执行之前 DOM 已经加载?” - Boris Callens
1个回答

121

很好的问题。

关于“将脚本放在页面底部”的建议以及它试图解决的问题,存在一些混淆。对于这个问题,我不打算讨论将脚本放在页面底部是否会影响性能/加载时间。我只想讨论一下,如果您还将脚本放在页面底部,是否需要使用$(document).ready

我假设您在那些立即调用脚本的函数中引用了DOM(任何简单的东西,如documentdocument.getElementById)。我还假设您只询问这些[引用DOM]文件。换句话说,库脚本或您的DOM引用代码所需的脚本(如jQuery)需要放在页面早期。

回答您的问题:如果您将DOM引用脚本包含在页面底部,则不需要使用$(document).ready

解释:如果没有像$(document).ready这样的onload相关实现,那么与页面中的DOM元素交互的任何代码都应该放在引用它的元素之后。最简单的方法是将该代码放置在</body>之前。请参见herehere。这也可以解决IE可怕的"Operation aborted" error问题。
话虽如此,这并不意味着不能使用$(document).ready。在DOM JavaScript中开始时引用未加载的对象是[其中之一]最常见的错误(我见过太多次了)。这是jQuery解决问题的方法,它不需要你考虑这个脚本相对于引用的DOM元素将被包含在哪里。这对于开发人员来说是一个巨大的胜利。这只是他们需要考虑的少了一件事。
此外,将所有引用DOM的脚本移动到页面底部通常是困难或不切实际的(例如,任何发出document.write调用的脚本必须保持原样)。其他时候,您使用的是渲染某些模板或创建一些动态JavaScript片段的框架,在其中引用需要在js之前包含的函数。

最后,过去“最佳做法”是将所有引用DOM的代码挤入window.onload中,但由于文档原因,已被$(document).ready实现所取代。

所有这些都导致$(document).ready成为引用DOM元素过早的问题的更优、实用和通用的解决方案。

5
如果您将DOM引用脚本放在页面底部,那么不需要使用$(document).ready。忽略您在后面提到的document.write问题,这个答案做出了一个天真的假设,即所有CSS都在javascript运行之前被下载和处理。这可能并不正确;浏览器可以并行下载外部文件。 - Powerlord
8
如果你有任何“defer”脚本,document ready会确保它们在就绪代码之前执行,但是句子中的“not entirely correct”不完全正确。参见:http://www.w3.org/TR/html5/the-end.html#the-end。 - Sam Saffron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接