javascript - 为什么 "this"比保存的选择器更有效?

标签 javascript jquery

我在做this test case查看使用 this 选择器可以加快进程的速度。在这样做的同时,我决定也尝试一下预先保存的元素变量,假设它们会更快。使用测试前保存的元素变量似乎是最慢的,这让我很困惑。我虽然只需要“找到”该元素一次就会极大地加快这个过程。为什么情况并非如此?

以下是我从最快到最慢的测试,以防有人无法加载它:

1

$("#bar").click(function(){
    $(this).width($(this).width()+100);
});
$("#bar").trigger( "click" );
<小时/>

2

$("#bar").click(function(){
    $("#bar").width($("#bar").width()+100);
});
$("#bar").trigger( "click" );
<小时/>

3

var bar = $("#bar");
bar.click(function(){
    bar.width(bar.width()+100);
});
bar.trigger( "click" );
<小时/>

4

par.click(function(){
    par.width(par.width()+100);
});
par.trigger( "click" );

我假设顺序是 4, 3, 1, 2,必须使用选择器更频繁地“查找”变量。

更新:我有一个 theory ,但如果可能的话,我希望有人验证这一点。我猜想在单击时,它必须引用变量,而不仅仅是元素,这会减慢速度。

最佳答案

修复测试用例:http://jsperf.com/this-vs-thatjames/10

TL;DR:每个测试中执行的点击处理程序数量都会增加,因为元素在测试之间不会重置。

微优化测试的最大问题是您必须非常非常小心地对待您正在测试的内容。在很多情况下,测试代码会干扰您正在测试的内容。这是一个example来自 Vyacheslav Egorov 的测试“证明”乘法在 JavaScript 中几乎是瞬时的,因为 JavaScript 编译器完全删除了测试循环:

// I am using Benchmark.js API as if I would run it in the d8.
Benchmark.prototype.setup = function() {
  function multiply(x,y) {
    return x*y;
  }
};

var suite = new Benchmark.Suite;
suite.add('multiply', function() {
  var a = Math.round(Math.random()*100),
      b = Math.round(Math.random()*100);

  for(var i = 0; i < 10000; i++) {
     multiply(a,b);
  }
})

由于您已经意识到存在违反直觉的情况,因此您应该格外小心。

首先,您不是在那里测试选择器。您的测试代码正在执行:零个或多个选择器(具体取决于测试)、函数创建(在某些情况下是闭包,其他情况下不是)、分配为单击处理程序以及触发 jQuery 事件系统。

此外,您正在测试的元素在测试之间会发生变化。很明显,一次测试的宽度比之前测试的宽度要大。但这还不是最大的问题。问题在于一个测试中的元素关联了 X 个单击处理程序。下一个测试中的元素具有 X+1 个点击处理程序。 因此,当您触发最后一个测试的点击处理程序时,您还会触发之前所有测试中关联的点击处理程序,从而使其比之前的测试慢得多。

我修复了 jsPerf,但请记住,它仍然不只测试选择器性能。尽管如此,影响结果的最重要因素还是被消除了。

<小时/>

注意:有一些slides和一个video关于使用 jsPerf 进行良好的性能测试,重点关注应避免的常见陷阱。主要思想:

  • 不要在测试中定义函数,而是在设置/准备阶段进行
  • 使测试代码尽可能简单
  • 比较具有相同功能的事物或坦率地说明这一点
  • 测试您想要测试的内容,而不是设置代码
  • 隔离测试,在每次测试之后/之前重置状态
  • 没有随机性。如果需要,请 mock 它
  • 注意浏览器优化(死代码删除等)

关于javascript - 为什么 "this"比保存的选择器更有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22596433/

相关文章:

javascript - 将下拉菜单放置在菜单标题的正下方

jquery - Angular2 和 jQuery : How to call component level function?

javascript - HTML & JS - 如何修改 CSS 类属性

javascript - 将值设置为 true 时,复选框不显示已选中

javascript - 在 Google Apps Script 上使用 Google Script API 获取开发者元数据

javascript - 如何使用 Intl.DateTimeFormat API 格式化毫秒

javascript - filepicker.io 在 Chrome 中阻止了 iframe

jQuery 限制显示的元素数量,比如 5

javascript - 更好的性能?在 Javascript/Jquery Mobile 中一次即可生成 200 多个单独的结果页面或 200 多个条件(如果是梯子或 switch 情况?)

javascript - 在使用 jQuery 扩展 DIV 时将高度设置为自动