38

好的,给牛仔装上鞍,因为这会很长。我整个上午都在浏览我的一些旧代码,我想知道最佳实践和优化。为了避免在主观车道上骑行,我将发布一些示例,其中包含一些希望易于回答的问题。我将尽量使示例保持简单,以便于回答并减少出错的可能性。开始了:

1) 赋值与 jQuery 调用

我知道在访问选择器时,通常认为将选择器分配给变量而不是多次进行相同的调用会更好 - 例如。

$('div#apples').hide();
$('div#apples').show();

对比

var oranges = $('div#oranges');
oranges.show();
oranges.hide();

引用 jQuery 时,同样的规则是否适用$(this)?前任。一个简单的脚本,使表格中的一些数据可点击并自定义链接。

$('tr td').each( function() {
    var colNum = $(this).index();
    var rowNum = $(this).parent().index();
    $(this).wrap('<a href="example.com/hello.html?column=' + colNum + '&row=' + rowNum +'">'); 
})

对比

$('tr td').each( function() {
    var self = $(this);
    var colNum = self.index()
    var rowNum = self.parent().index()
    self.wrap('<a href="example.com/hello.html?column=' + colNum + '&row=' + rowNum +'">'); 
});

2)this对比$(this)

好的,所以下一个是我想知道很长时间的事情,但我似乎找不到任何关于它的信息。请原谅我的无知。什么时候调用 vanilla jsthis而不是 jQuery Wrapped才有意义$(this)?我的理解是——

$('button').click(function() {
  alert('Button clicked: ' + $(this).attr('id'));
});

比访问 vanillathis对象的 DOM 属性效率低得多,如下所示 -

$('button').click(function() {
  alert('Button clicked: ' + this.id);
});

我了解那里发生了什么,我只是想知道在决定使用哪个时是否有经验法则可以遵循。

3)更多的特异性总是更好吗?

这很简单,我们的选择器更具体总是有益的吗?很容易看出这$('.rowStripeClass')会比 慢得多$('#tableDiv.rowStripeClass'),但是我们在哪里画线呢?$('body div#tableDiv table tbody tr.rowStripeClass')还是更快?任何输入将不胜感激!

如果您已经做到了这一点,感谢您的关注!如果你还没有,:p ​</p>

4

6 回答 6

37

我会尽量简洁地回答这些问题:

  1. 经常使用时缓存它,尤其是在循环情况下,运行相同的代码以获得相同的结果对性能来说永远不是一件好事,缓存它。

  2. this当您只需要一个 DOM 元素并且$(this)需要jQuery 方法(否则将不可用)时使用,您的 vs 示例非常this.id完美$(this).attr("id"),还有一些更常见的示例:

    • 使用this.checked代替$(this).is(':checked')
    • 使用$.data(this, 'thing')代替$(this).data('thing')
    • 创建 jQuery 对象的任何其他情况基本上都没有用。
  3. 从 ID 选择器中降序对于性能来说是首选...您需要多具体?简而言之,这完全取决于:尽可能具体

于 2010-07-12T17:46:33.623 回答
9

1) 赋值与 jQuery 调用

引用 jQuery 的 $(this) 时,同样的规则是否适用?

是的,一点没错。对该$函数的调用会创建一个新的 jQuery 对象,并且随之而来的是相关的开销。多次调用$同一个选择器每次都会创建一个新对象。

2)这个与$(这个)

我会说知道差异很重要,因为有时不使用 jQuery 包装对象变得至关重要。在大多数情况下,您不想进行过早的优化,只是为了保持一致,总是用 $(this) 包装它们,最好将其缓存在一个变量中。<ul>但是,考虑这个包含一百万个<li>元素的无序列表的极端示例:

$("#someList  li").each(function() {
    var id = $(this).attr('id');
});

将创建一百万个新对象,这将导致显着的性能损失,而您本可以完全不创建任何新对象。对于跨所有浏览器一致的属性和属性,您可以直接访问它们而无需将其包装在 jQuery 中。但是,如果这样做,请尝试将其限制在处理大量元素的情况下。

3)更多的特异性总是更好吗?

不总是。它主要取决于浏览器,并且再次不值得深入研究微优化,除非您确定某些东西在您的应用程序中运行得相当慢。例如:

$("#someElement") vs $("#someElement", "#elementsContainer")

看起来,由于我们在通过 id 搜索元素时也提供了上下文,所以第二个查询会更快,但事实恰恰相反。第一个查询转换为对本机的直接调用,getElementById(..)而第二个查询则不是因为上下文选择器。

此外,一些浏览器可能会提供一个接口来通过类名访问元素 usinggetElementsByClassName并且 jQuery 可能会为这些浏览器使用它以获得更快的结果,在这种情况下提供更具体的选择器,例如:

$("#someElement.theClass")

实际上可能是一个障碍,而不是简单地写:

$(".theClass")
于 2010-07-12T18:00:30.927 回答
4

这个博客并不太过时,但它为您的问题提供了一些答案,并提供了一些有关在使用 jquery 时加速您的网站的更多信息:http ://www.artzstudio.com/2009/04/jquery-performance-规则/

我的最爱之一是限制 DOM 操作的第六条。在 for 循环中执行 .append 总是一件坏事,因为每次追加到 DOM 时,这是一项昂贵的操作。

于 2010-07-12T17:44:42.803 回答
4

取决于您的问题:

  1. 缓存 jQuery 对象应该会产生最佳性能。它将避免 DOM 查找,这在多次执行时会变慢。您可以从 jQuery 链接中受益——有时不需要局部变量。
  2. 当 $(this)this是一个 DOM 元素时也是如此。尽管这是获取 jQuery 对象的最快方式,但它仍然比缓存慢。如果 vanilla DOM 元素就足够了——那么根本就不要调用 jQuery。具有 id 属性的示例非常好 - 如果您不需要 $(this),则更喜欢 this.id 而不是 $(this).attr('id)
  3. 更具体的选择器确实会减少 DOM 查找时间。然而,确实有一条线要画——只有当你 100% 确定这会以明显的方式提高性能时,才能使选择器更加具体。
于 2010-07-12T17:49:26.457 回答
3

您应该注意的唯一情况是循环事件。因为您在其中一个中所做的每一个动作都将在每次迭代或每个事件中完成。

  1. 赋值与 jQuery 调用

    你的例子不是最好的。您应该保存对 jQuery 对象的引用的位置是循环事件中使用的对象,或者是复杂查询的结果。

  2. 这与 $(这)

    同样在性能关键的情况下,原始 dom更好。除此之外,您应该选择哪个更短或更易读。惊喜,惊喜并不总是 jQuery。

  3. 更多的特异性总是更好吗?

    还有更多类型的特异性通常被人们混淆。其中一个无用的,例如:id 选择器的标签名称tag#id,它会比简单的 id 慢。但是还有另一种类型,当具体化将是一个巨大的好处时。现在这种类型取决于浏览器,因为现代浏览器会牺牲旧浏览器,但值得权衡取舍 当您tag为 a指定 a 时,就会发生这种情况class tag.class。在 IE 6-7 中它会比 simple 快得多.class,因为 sizzle 可以利用 fastdocument.getElementsByTagName功能。现在另一种类型是当您指定太多祖先时。这会在每个浏览器中减慢速度。这是因为选择器是从右到左执行的。要记住的规则:始终尽可能具体地成为最右边的选择器

于 2010-07-12T17:59:53.850 回答
1

2013 年关于最佳 jQuery 实践的博客文章

更新了您的问题的答案,甚至更多关于当今应用的最佳 jQuery 实践的更多信息,本文正在处理非常有用且您可能想阅读的有趣主题。

它涉及这里提出的主题,甚至更多:动画功能、jQuery 承诺、导入 jQuery 的最佳方法、jQuery 事件等。希望对您有所帮助!

于 2013-07-19T09:45:47.780 回答