这里的人们经常建议缓存从jQuery
元素创建的DOM
对象,就像使用以下代码一样:
$('#container input').each(function() {
$(this).addClass('fooClass');
$(this).attr('data-bar', "bar");
$(this).css('background-color', 'red');
});
答案 0 :(得分:52)
在jQuery tag info中出现此警告:
jQuery函数$()很昂贵。反复调用它是非常低效的。
嗯......这对于字符串选择器来说是正确的,它会被正则表达式解析以找出它们是什么:
quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/
然后,如果字符串是一个选择器(id
除外),jQuery遍历DOM以找到与其昂贵的find
函数的匹配:
} else if ( !context || context.jquery ) {
return ( context || rootjQuery ).find( selector );
}
所以是的,这是昂贵的,但这只适用于选择者!
如果我们传递DOMElement
,jQuery所做的唯一操作就是将DOMElement参数保存为新创建的jQuery对象的上下文,并将上下文的长度设置为1:
// Handle $(DOMElement)
if ( selector.nodeType ) {
this.context = this[0] = selector; // Selector here is a DOMElement
this.length = 1;
return this;
}
我做了some tests with jsPerf,我发现确实缓存jQuery对象只有一点影响:
在Chrome中它的速度只有7%。 (在IE中,它有点重要:12%。)
答案 1 :(得分:14)
要回答第二个问题,请查看source:
// Handle $(DOMElement)
if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
}
答案 2 :(得分:10)
关于性能差异,如果您正在寻找两者之间的直接比较,那么删除任何可能会导致结果偏差的额外代码会很有帮助,例如DOM选择和其他不直接相关的方法。< / p>
在更真实的世界环境中,相对差异很小,因为您的测试显示
要记住的另一件事是每次创建一个jQuery对象时,都需要为它分配内存,这会增加垃圾收集器需要做的工作。
所以我认为人们建议缓存的原因在某种程度上是有原则的。正在进行额外的工作,虽然它通常不会产生明显的影响,但最终还是需要一些可以轻易避免的开销。
答案 3 :(得分:8)
所有运行时性能测试遗漏的一件事是另一个主要考虑因素:
网络带宽。
将$(this)
缓存到局部变量中通常会减小脚本的大小,特别是在缩小时(因为this
不能从四个字符中减少)。
考虑:
function hello(text) {
$(this).attr();
$(this).css();
$(this).data();
$(this).click();
$(this).mouseover();
$(this).mouseleave();
$(this).html(text);
}
hello('Hello world');
Closure编译器的缩小输出是
function hello(a){$(this).attr();$(this).css();$(this).data();$(this).click();$(this).mouseover();$(this).mouseleave();$(this).html(a)}hello("Hello world");
这节省了39个字节(20%)。现在考虑:
function hello(name) {
var $this = $(this);
$this.attr();
$this.css();
$this.data();
$this.click();
$this.mouseover();
$this.mouseleave();
$this.html(name);
}
hello('Hello world');
缩小的输出是
function hello(b){var a=$(this);a.attr();a.css();a.data();a.click();a.mouseover();a.mouseleave();a.html(b)}hello("Hello world");
这节省了74个字节(37%),几乎使我们的字节节省了一倍。显然,在大型脚本中实际节省的成本会更低,但您仍然可以通过缓存来大幅减少脚本的大小。
真的,缓存$(this)
只有一个好处。您可以获得微不足道但可测量的运行时性能提升。更重要的是,您可以减少通过网络传输的字节数,并将直接转换为更多美元,因为faster page loads equal more sales。
当你以这种方式看待它时,你实际上可以说重复$(this)
而不是缓存它是可量化的美元成本。