一次又一次地使用相同的查询选择器是否会产生性能成本?

Is there a performance cost to using the same query selector again and again?

在文档中搜索相同查询选择器的性能成本是否加起来很重要,或者管道中是否有一些代码——来自正在使用的 JavaScript 库(例如 jquery) 或 JavaScript 引擎或浏览器引擎 -- 缓存查询选择器。

$(document).ready(function() {

  var foo = $("#foo");

  doThis();
  doThat();
  thenDoThat();
  ...

  function doThis() {
    $("#foo")...
    ...
  }

  function doThat() {
    $("#foo")...
    ...
  }

  function thenDoThat() {
    $("#foo")...
    ...
  }

  ...
});

我确实了解对象的生命周期,尤其是。在垃圾收集环境中。所以,对象的范围将决定它的生命周期的回答不能完全满足我的好奇心,因为这个事实是显而易见的。

我的问题确实是,如果我一遍又一遍地访问 $("#foo")

  1. 加起来会花费大量 CPU 时间,因此将其缓存在我的代码中的适当级别会避免此类成本,或者

  2. 一些代码已经缓存了它,或者

  3. 是不是做多少次都可以忽略不计?

是的,这会影响性能。每$(selector)运行s,必须构造一个新的jQuery对象。也就是说,除非您在短时间内运行 数量巨大,否则影响很小。例如:

const t1 = performance.now();

for (let i = 0; i < 300000; i++) {
  const html = $('div').html();
}

const t2 = performance.now();

const div = $('div');
for (let i = 0; i < 300000; i++) {
  const html = div.html();
}

const t3 = performance.now();

console.log(t2 - t1);
console.log(t3 - t2);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>foo</div>

构造 jQuery 对象确实花费了非零的 CPU 时间,但仍然不多。如果你 do 不得不担心效率,你可能只使用标准 Javascript 代替,这将比 jQuery 方法有额外的改进(甚至超过保存对jQuery 对象)。

const t1 = performance.now();
for (let i = 0; i < 300000; i++) {
  const html = $('div').html();
}
const t2 = performance.now();

const $div = $('div');
for (let i = 0; i < 300000; i++) {
  const html = $div.html();
}
const t3 = performance.now();

for (let i = 0; i < 300000; i++) {
  const html = document.querySelector('div').innerHTML;
}
const t4 = performance.now();

const div = document.querySelector('div')
for (let i = 0; i < 300000; i++) {
  const html = div.innerHTML;
}
const t5 = performance.now();

console.log('jQuery re-selection', t2 - t1);
console.log('jQuery saving reference', t3 - t2);
console.log('vanilla re-selection', t4 - t3);
console.log('vanilla saving reference', t5 - t4);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>foo</div>