为什么jQuery.ready在它如此慢的时候推荐?

时间:2012-03-04 18:55:48

标签: javascript jquery performance optimization domready

我之前曾问过similar question,但我从未明确表达过我的观点,或者至少我认为这是一个相关的问题,值得提出来,看看是否有人能提出一些有见地的想法。< / p>

使用jQuery时,我们中的许多人在加载DOM时使用jQuery.ready函数执行init。它已成为使用jQuery将DOM操作程序添加到网页的事实上的标准方法。某些浏览器存在相关事件natively,但jQuery在其他浏览器中模拟它,例如某些IE版本。例如:

<head>
<script>
    var init = function() { alert('hello world'); };
    $.ready(init);
</script>

现在,我们所有的测试都显示此事件可能非常缓慢。它并不像window.onload那么慢,但在执行之前它仍然经常延迟大约100毫秒。如果FF可以达到200-300毫秒,特别是在刷新时。

这些是非常重要的毫秒,因为这是在进行任何DOM操作之前显示初始布局的时间量(例如隐藏下拉列表)。很多时候,布局“闪烁”主要是由于使用缓慢的DOM就绪事件,迫使程序员使用CSS隐藏元素,并可能使其不易访问。

现在,如果我们在关闭body标签之前将init函数放在脚本标记中,它将更快地执行,通常大约一半时间但有时甚至更快:

<head>
<script>
    var init = function() { alert('hello world'); };
</script>
</head>
<body>
<!-- some HTML -->
<script>init();</script>
</body>

一个证明差异的简单测试页:http://jsbin.com/aqifon/10

我的意思是,我们并没有谈论几乎没有明显的差异,因为一些“优化警察”在使用有效选择器时会提升。在进行DOM操作onload时,我们正在讨论一些主要延迟。在FF中尝试这个例子,domready有时会慢100多倍(300ms vs 2ms)。

现在问我的问题:为什么jQuery.ready建议使用它显然比其他选择慢得多?在关闭BODY与使用init之前调用jQuery.ready有什么缺点?可以说使用domReady更“安全”,但在什么情况下它比其他选项更安全? (我正在考虑像document.write和延迟脚本这样的东西)我们在许多客户端网站上使用BODY方式将近5年,我们从未遇到过任何问题。它的速度要快得多。

我也很想知道,因为有很多关于jsPerf和优化选择器的模糊,每10000次执行几毫秒,为什么没有太多谈论这个?它基本上是用户面临的第一个延迟,并且在每个页面加载时切片50-100毫秒似乎相当简单......

4 个答案:

答案 0 :(得分:8)

首先要点:

不,在关闭init之前致电<body>没有任何不利之处。您会注意到,依靠$.ready()和也将完美地与所有浏览器一起使用(即使在IE上)。

现在,有理由使用$.ready(),在您的情况下它们可能不适用:

  1. $.ready()使开发人员可以轻松按正确的顺序执行操作。特别是,关键是不要引用尚未加载的DOM元素。虽然这很简单,但许多开发人员仍然觉得它令人困惑。 $.ready()是一个明智的选择,虽然速度很慢。
  2. 在您说过几个需要init()的脚本时,手动在您身体末端执行此操作并不一定容易/方便。它需要纪律和知识这些脚本的功能。特别是你经常会在依赖于jQuery的库中看到$.ready(),因为无论开发人员用什么方式加载lib,它都可以工作。
  3. 使用异步模块定义(例如require.js)作为加载javascript的方式变得流行,<body/>方法的结束无法保证。

答案 1 :(得分:6)

一个优点是,您可以将代码放在页面的任何位置。在我们的案例中,我们在CMS中使用模板系统,将页面拼接在一起,大约10-30个模板用于不同的部分(取决于复杂性)。

由于您希望模板可以在任何使用的页面上运行,因此您需要在其中包含必要的Javascript。对于这些情况,ready()功能是一个真正的救星。

答案 2 :(得分:2)

如果您编写了一个其他人在其页面中包含的JS文件,那么在该文件中使用document.ready更安全(假设它需要在DOM准备好后自动进行一些处理),因为您不能确保文件是否包含在头部或身体的末端。

当涉及到您完全控制的页面时,显然您没有那么担心,所以我没有看到使用document.ready而不是调用您的{{1}更加“安全”从身体的末端开始。使用document.ready(或onload)并将脚本放在正文的末尾是两种最常用的方法,它们很常见,因为它们都运行良好。

你提到init()是一个可能的例外,但你不想从document.ready或身体的末尾调用它,因为整个页面的任何一种方式都已被解析。

答案 3 :(得分:0)

因为它使domReady和window.load变慢。

可以轻松优化指标,而不是实际的用户体验。因此,即使交互性被延迟,“真实用户优化”图也会下降。