jQuery 优化/最佳实践
Posted
技术标签:
【中文标题】jQuery 优化/最佳实践【英文标题】:jQuery Optimization/Best Practices 【发布时间】:2011-03-14 22:18:36 【问题描述】:好的,给牛仔装上鞍,因为这将是一个很长的时间。我整个上午都在浏览我的一些旧代码,我想知道最佳实践和优化。为了避免在主观车道上骑行,我将发布一些示例,其中包含一些希望易于回答的问题。我将尽量使示例保持简单,以便于回答并减少出错的可能性。我们开始:
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 js this
而不是 jQuery 包装的 $(this)
有意义?这是我的understanding -
$('button').click(function()
alert('Button clicked: ' + $(this).attr('id'));
);
比访问 vanilla this
对象的 DOM 属性效率低得多,如下所示 -
$('button').click(function()
alert('Button clicked: ' + this.id);
);
我知道那里发生了什么,我只是想知道在决定使用哪个时是否有经验法则可以遵循。
3) 特异性越高越好吗?
这个非常简单,使用我们的选择器更具体是否总是有益的?很容易看出$('.rowStripeClass')
会比$('#tableDiv.rowStripeClass')
慢得多,但我们在哪里划清界限呢? $('body div#tableDiv table tbody tr.rowStripeClass')
还更快吗?任何意见将不胜感激!
如果您已经做到了这一点,感谢您的关注!如果你还没有,:p
【问题讨论】:
【参考方案1】:关于最佳 jQuery 实践的 2013 年博客文章
更新了关于您的问题的答案,甚至更多关于当今应用的最佳 jQuery 实践的更多信息,this article 正在处理非常有用且您可能想阅读的有趣主题。
它处理这里所问的主题,甚至更多:动画函数、jQuery 承诺、导入 jQuery 的最佳方法、jQuery 事件等。 希望对您有所帮助!
【讨论】:
【参考方案2】:唯一需要注意的情况是循环和事件。因为您在其中一个中所做的每一个动作都将在每次迭代或每个事件中完成。
赋值与 jQuery 调用
你的例子不是最好的。您应该保存对 jQuery 对象的引用的地方是 loops 或 events 中使用的那些,或者是 复杂查询 的结果。。 p>
this 与 $(this)
再次在性能关键情况下原始dom更好。 其他,您应该选择更短或更可读。惊喜,惊喜并不总是 jQuery。
更多的特异性总是更好吗?
有更多类型的特异性通常被人们混淆。 其中一个是无用,例如:id 选择器tag#id
的标签名称,它会比简单的id 慢。但是还有另一种类型,具体来说,它会带来巨大的好处。
现在这种类型取决于浏览器,因为现代浏览器会牺牲旧浏览器,但值得权衡取舍 当您为class
tag.class
指定tag
时,就会发生这种情况。在 IE 6-7 中,它将比简单的.class
快得多,因为 sizzle 可以利用快速的document.getElementsByTagName
函数。现在另一种类型是当您指定太多祖先时。这将在每个浏览器中减慢速度。这是因为选择器是从右到左执行的。要记住的规则:始终尽可能具体地成为最右边的选择器。
【讨论】:
我学到的越多越不奇怪,jQuery 并不总是答案:)【参考方案3】:1) 赋值与 jQuery 调用
在引用 jQuery 的 $(this) 时,同样的规则是否适用?
是的,当然。对$
函数的调用会创建一个新的jQuery 对象,并带来相关的开销。使用同一个选择器多次调用$
每次都会创建一个新对象。
2) 这个 vs $(this)
我会说知道区别很重要,因为有时不使用 jQuery 包装对象变得至关重要。在大多数情况下,您不想进行过早的优化,只是为了保持一致,总是用 $(this) 包装它们,最好将其缓存在一个变量中。但是,考虑一下包含一百万个<li>
元素的无序列表<ul>
的极端示例:
$("#someList li").each(function()
var id = $(this).attr('id');
);
将创建一百万个新对象,这将导致显着的性能损失,而您完全可以在不创建任何新对象的情况下完成。对于跨所有浏览器一致的属性和属性,您可以直接访问它们而无需将其包装在 jQuery 中。但是,如果这样做,请尝试将其限制在处理大量元素的情况。
3) 特异性越高越好吗?
并非总是如此。它主要取决于浏览器,并且再次不值得深入研究微优化,除非您确定某些东西在您的应用程序中运行得相当慢。例如:
$("#someElement") vs $("#someElement", "#elementsContainer")
看起来,由于我们在通过 id 搜索元素时也提供了上下文,因此第二个查询会更快,但事实恰恰相反。第一个查询转换为对本机 getElementById(..)
的直接调用,而第二个不是因为上下文选择器。
此外,一些浏览器可能会提供一个接口来使用 getElementsByClassName
来按类名访问元素,而 jQuery 可能会为这些浏览器使用它以获得更快的结果,在这种情况下提供更具体的选择器,例如:
$("#someElement.theClass")
可能实际上是一个障碍,而不是简单的写作:
$(".theClass")
【讨论】:
关于您的最后一个示例,#someElement
将总是比类查找更快。 getElementById()
是最快的,它是一个独特的查找,通常针对隐藏的哈希表。对于其他示例,它们是有效的注释,但请记住它们不是等价的,例如:如果您只想选择#someElement
(如果它在#elementsContainer
内)怎么办?在任何一种情况下,使用 $("#elementsContainer #someElement")
而不是 $("#someElement", "#elementsContainer")
来提高性能,使用上下文,但如果它是另一个选择器,则不是,它是一个额外的 Sizzle 调用。
@Nick - #someElement
总是像你说的那样最快,因为它转换为 getElementById
。但是,#someElement.someClass
与 (context || rootjQuery).find( selector )
和 getElementById
不同。在 id 调用中传递选择器字符串甚至元素作为上下文总是会减慢速度,因此即使$("#someElement", $("#elementsContainer"))
也会比$("#someElement")
慢。您关于两个示例不等效的观点非常有效,但这只是为了举例说明向范围添加更多内容并不总是有帮助。【参考方案4】:
回答您的问题:
-
缓存 jQuery 对象应该会产生最佳性能。它将避免 DOM 查找,这在多次执行时会变慢。您可以从 jQuery 链接中受益 - 有时不需要局部变量。
当
this
是一个DOM 元素时,$(this) 也是如此。尽管这是获取 jQuery 对象的最快方式,但它仍然比缓存慢。如果 vanilla DOM 元素就足够了——那么根本就不要调用 jQuery。具有 id 属性的示例非常好 - 如果您不需要 $(this),则更喜欢 this.id 而不是 $(this).attr('id)
更具体的选择器确实会减少 DOM 查找时间。但是,确实有一条线要画 - 只有当您 100% 确定这会显着提高性能时,才能使选择器更加具体。
【讨论】:
【参考方案5】:我会尽量简洁地回答这些问题:
经常使用时缓存它,尤其是在循环的情况下,运行same代码得到same的结果是对性能来说从来都不是一件好事,缓存它。
当你只需要一个DOM元素时使用this
,当你需要the jQuery methods时使用$(this)
(否则将不可用),你的this.id
与$(this).attr("id")
的例子是完美的,一些更常见例子:
this.checked
代替$(this).is(':checked')
使用$.data(this, 'thing')
而不是$(this).data('thing')
创建 jQuery 对象的任何其他情况基本上没有用处。
从 ID 选择器降序对于性能而言是首选...您需要具体到什么程度?简而言之,这完全取决于:尽可能具体。
【讨论】:
感谢尼克的洞察力!正如 Patricia 所说,总是有很好的答案。 基于受欢迎程度,我会接受这个作为答案。我觉得大多数其他答案也非常有用,所以我尽可能 +1! 为什么$.data(this, 'thing');
比$(this).data('thing');
好?使用$(this)
是否需要再次查找或其他内容? +1 顺便说一句,很好的答案!【参考方案6】:
这个博客并不过时,但它为您的问题提供了一些答案,并提供了一些有关在使用 jquery 时加速您的网站的更多信息:http://www.artzstudio.com/2009/04/jquery-performance-rules/
我的最爱之一是限制 DOM 操作的第六条。在 for 循环中执行 .append 总是一件坏事,因为每次追加到 DOM 时,这是一项昂贵的操作。
【讨论】:
非常棒的博文。肯定 +1。以上是关于jQuery 优化/最佳实践的主要内容,如果未能解决你的问题,请参考以下文章