拥有100个文档准备好是否比1个文档准备好更好或更差?

11

想知道调用 document.ready 函数的次数是否会影响页面加载速度。 在 Gulp / Grunt 中,是否有一种方法可以通过删除单独的 document ready 函数来压缩 / 缩小 JS 代码?


2
你为什么想要多个 document.ready - Mairaj Ahmad
请展示您的代码,也许能帮助别人解决您的问题。 - wolendranh
2
@Leopard,它们总是很多。例如,几乎任何脚本都会为自己的目的使用一个。 - Qwertiy
1
@Leopard OP可能会问这个问题,是因为他正在考虑重构他现有的代码库,使所有脚本都从一个单一的文档就绪中触发。 - El Dorado
2
人们认为会严重影响代码性能的事情和实际上会严重影响代码性能的事情似乎从来都不相关... - BlueRaja - Danny Pflughoeft
4个回答

19

检查一下!

我在Chrome中没有看到显著的差异。
据我所知,这对IE8至关重要,但我没有检查这个事实。
IE11在第一个片段上显示2秒,而其他片段仅需200毫秒。

此外,似乎jQuery已经聚合了加载事件。

别忘了

  1. 当您在一个选项卡中运行相同的代码时,浏览器会记住某些内容,并使其运行更快。
  2. 重新加载页面是不够的。请改为打开新选项卡。
  3. 打开新选项卡后,请以不同的顺序运行片段。
  4. 如果片段在标签页上首先运行,它将比其他三个片段更慢。

for (var q=0; q<1000; ++q) {
  document.addEventListener('DOMContentLoaded', (function (i) {
    console.log(i);
  }).bind(null, q));
}

document.addEventListener('DOMContentLoaded', function () {
  document.querySelector('output').textContent = performance.now().toFixed(3);
});
<output></output>

document.addEventListener('DOMContentLoaded', function () {
  for (var q=0; q<1000; ++q) {
    (function (i) {
      console.log(i)
    }).bind(null, q)();
    
    document.querySelector('output').textContent = performance.now().toFixed(3);
  }
});
<output></output>

for (var q=0; q<1000; ++q) {
  $((function (i) {
    console.log(i);
  }).bind(null, q));
}

$(function () {
  document.querySelector('output').textContent = performance.now().toFixed(3);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<output></output>

$(function () {
  for (var q=0; q<1000; ++q) {
    (function (i) {
      console.log(i)
    }).bind(null, q)();
    
    document.querySelector('output').textContent = performance.now().toFixed(3);
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<output></output>

可能只有我这个避开 JavaScript 的人会注意到,但是这些脚本中没有使用 document.ready。如果你们 JavaScript 这些人谈论 document.ready ,那么它是否是 addEventListener('DOMContentLoaded') 的同义词?
有两个事件:DOMContentLoadedload (window.onload)。第一个事件发生在 body 解析完成时,但某些资源仍在加载中。第二个事件发生在页面完全加载后。第一个事件很适合运行包含 DOM 操作的脚本,但是并不是所有浏览器都支持它。
因此,jQuery 使用了这两个事件中的第一个,而经典的订阅方式是:
$(document).ready(function () {
  // ...
});

但是在一些版本之后,它被简化为直接将函数传递到jQuery中:

$(function () {
  // ...
});

所以在原始的示例中,我使用了2个事件中的第一个,在jQuery示例中,我使用了对其进行订阅的简短形式。由于不支持此事件的浏览器非常古老,因此可以正确地假定jQuery始终使用DOMContentLoaded(可能load方法已在版本2中删除 - 没有检查过,但我认为没有保留它的理由)。


1
也许只有我作为一个避免使用JavaScript的人,但是没有一个脚本里面有document.ready。如果你们JS开发者谈论document.ready,那么这是addEventListener('DOMContentLoaded')的同义词吗? - Thomas Weller
@Thomas,已更新答案并回答了你的问题。 - Qwertiy
对于IE 11:2469毫秒,288毫秒,1361毫秒和321毫秒。这里有显著的差异。好吧...在那些具有1000个文档准备脚本且函数本身运行时间很短的情况下,你在做什么?在任何其他情况下,那2.4毫秒的开销不会对文档准备中的一个函数运行产生影响。 - Sumurai8
@Thomas,jQuery中的document.ready实际上是一个Promise,只要检测到document.readyState === 'complete'就会被解决。 DOMContentLoaded事件是检查document.readyState状态的信号之一。 - zzzzBov
@Sumurai8,我在IE11(Win 7)上进行了检查,两种jQuery的方式之间没有任何区别。你确定第三个脚本不是你在页面上首先运行的吗?关于第一个脚本- 是的,在那里需要2秒钟。 - Qwertiy
可能是因为我在那个时间点上没有缓存那个jQuery版本。或者是这台机器所在的云服务器在加载一个非常简单的页面时出了一些问题。现在它也返回一个较低的数字。 - Sumurai8

4

许多文档就绪调用不应对应用程序性能产生太大影响。最好的解决方案可能是只有一个并在其中初始化所有所需内容。但这取决于您的应用程序结构,您可能更喜欢拥有多个。无论如何,我认为没有任何 Gulp 任务可以将不同的就绪函数包装在一起,因为它会触及应用程序逻辑。


4
你可以有多个,但不总是最好的选择。尽量不要过度使用它们,因为这会严重影响可读性。除此之外,它是完全合法的。
还值得注意的是,在一个$(document).ready块中定义的函数不能从另一个$(document).ready块中调用。
$(document).ready(function() {
    alert('hello1');
    function saySomething() {
        alert('something');
    }
    saySomething();

});
$(document).ready(function() {
    alert('hello2');
    saySomething();
});

输出结果为:
hello1
something
hello2

检查这个帖子这个

更详细的答案请参考:https://dev59.com/yHM_5IYBdhLWcg3wjj6r - Gopinath Shiva

2

是的,你可以使用多个文档就绪处理程序,在几个地方使用jQuery代码没有特殊的优势。由于这些处于不同的作用域中,因此不能在一个变量内部使用另一个变量。

实际上,jQuery事件处理程序将函数推入特定事件的队列中以执行。当事件被触发时,所有函数都将根据父顺序函数的返回值从特定事件行/堆栈/队列中依次执行。
但是需要注意的是,每个$(document).ready()函数调用必须返回。如果其中一个函数抛出异常,则后续调用将永远不会运行。

$(document).ready(function() {
    document.write('<h3>In First ready function</h3>');
    var foo = function() {
        console.log('inside foo');
    }
    document.write("foo:" +(typeof foo)+"<br>");
    document.write("bar:" +(typeof bar)+"<br>");
    
});
$(document).ready(function() {
   document.write('<h3>In Second ready function</h3>');
    
    var bar=function bar() {
        console.log('inside bar');
    }
    document.write("foo:" +(typeof foo)+"<br>");
    document.write("bar:" +(typeof bar)+"<br>");
    
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

实际上,jQuery的$(document).ready()方法是使用addEventListener方法将函数与DOMContentLoaded事件一起附加的。

是的,您可以在单个页面上拥有多个它的实例。没有特定的优势。所有实例都会按照首次调用的顺序执行。


1
你的回答底部包含在一个块引用中,但没有链接到引用的来源。它实际上是在引用什么吗?如果是, 请确认来源。如果不是(即这是你自己的话),请删除块引用标记,以便它不会显示为块引用。 - Anthony Grist
@AnthonyGrist,我已经删除了引用,这是我的原话,请取消您的反对。 - Haresh Vidja

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