例如,第一段代码是否会执行两次完整搜索,或者如果没有发生DOM更改,它是否足够智能以缓存结果?
if ($("#navbar .heading").text() > "") {
$("#navbar .heading").hide();
}
和
var $heading = $("#navbar .heading");
if ($heading.text() > "") {
$heading.hide();
}
如果选择器更复杂,我可以想象这是一个非常重要的命中。
答案 0 :(得分:28)
使用相同的选择器不断反复调用$( selector )
是浪费的。
或几乎总是......您通常应该在本地变量中保留jQuery对象的缓存副本,除非您预期它已经更改或者您只需要它一次。
var element = $("#someid");
element.click( function() {
// no need to re-select #someid since we cached it
element.hide();
});
答案 1 :(得分:16)
jQuery没有,但是有可能在表达式中分配变量,然后在后续表达式中重用它们。所以,缓存你的例子......
if ((cached = $("#navbar .heading")).text() > "") {
cached.hide();
}
下行是因为它使代码更加琐碎,而且难以理解。
答案 2 :(得分:14)
这不是“它是什么吗?”,而是“可以吗?”,不,它不能 - 自上次运行查询以来,您可能已经向DOM添加了其他匹配元素。这会使缓存的结果失效,并且除了再次运行查询之外,jQuery没有(合理的)方式告诉其他。
例如:
$('#someid .someclass').show();
$('#someid').append('<div class="someclass">New!</div>');
$('#someid .someclass').hide();
在此示例中,如果查询有任何缓存,则不会隐藏新添加的元素 - 它只会隐藏先前显示的元素。
答案 3 :(得分:12)
我刚刚采用了解决此问题的方法:
var cache = {};
function $$(s)
{
if (cache.hasOwnProperty(s))
{
return $(cache[s]);
}
var e = $(s);
if(e.length > 0)
{
return $(cache[s] = e);
}
}
它的工作原理如下:
$$('div').each(function(){ ... });
据我所知,基于这个简单的检查,结果是准确的:
console.log($$('#forms .col.r')[0] === $('#forms .col.r')[0]);
注意,它会破坏您的MooTools实现或使用$$
表示法的任何其他库。
答案 4 :(得分:9)
我不认为这样做(虽然我现在不想通过阅读3.5万行JavaScript来确定)。
但是,你正在做的事情不需要多个选择器 - 这应该有效:
$("#navbar .heading:not(:empty)").hide();
答案 5 :(得分:6)
与你的$$方法类似,我创建了一个函数(同名),它使用记忆模式来保持全局清洁,并且还考虑了第二个上下文参数...就像$$(“。class”,“ #context“)。如果你使用返回$$后发生的链式函数find(),则需要这样做;因此,除非先缓存上下文对象,否则不会单独缓存它。我还在结尾添加了布尔参数(第二个或第三个参数取决于你是否使用上下文)来强制它返回DOM。
代码:
function $$(a, b, c){
var key;
if(c){
key = a + "," + b;
if(!this.hasOwnProperty(key) || c){
this[key] = $(a, b);
}
}
else if(b){
if(typeof b == "boolean"){
key = a;
if(!this.hasOwnProperty(key) || b){
this[key] = $(a);
}
}
else{
key = a + "," + b;
this[key] = $(a, b);
}
}
else{
key = a;
if(!this.hasOwnProperty(key)){
this[key] = $(a);
}
}
return this[key];
}
用法:
<div class="test">a</div>
<div id="container">
<div class="test">b</div>
</div>
<script>
$$(".test").append("1"); //default behavior
$$(".test", "#container").append("2"); //contextual
$$(".test", "#container").append("3"); //uses cache
$$(".test", "#container", true).append("4"); //forces back to the dome
</script>
答案 6 :(得分:4)
我不相信jquery会对选择器进行任何缓存,而是依赖于下面的xpath / javascript来处理它。话虽如此,您可以在选择器中使用许多优化。这里有一些文章涵盖了一些基础知识:
答案 7 :(得分:3)
这个$$()工作正常 - 应该返回一个有效的jQuery对象,在任何情况下都是永不定义的。
小心吧!它应该/不能与动态可能改变的选择器,例如。通过附加与选择器匹配的节点或使用伪类。
function $$(selector) {
return cache.hasOwnProperty(selector)
? cache[selector]
: cache[selector] = $(selector);
};
当然,$$可以是任何功能名称。
答案 8 :(得分:2)
John Resig在JQuery Camp 2008的Jquery Internals演讲中确实提到了一些浏览器支持在修改DOM时触发的事件。对于这种情况,可以缓存Selctor结果。
答案 9 :(得分:2)
有一个名为jQache的好插件就是这样做的。 安装插件后,我通常会这样做:
var $$ = $ .q;
然后只是
$$(“#navbar .heading”)。hide();
所有这一切的最好的部分是,如果你正在做动态的东西,你也可以在需要时刷新你的缓存,例如:
$$(“#navbar .heading”,true).hide(); //刷新缓存并隐藏新的(新发现的)#navbar .heading
并且
$$清晰(); //完全清除缓存
答案 10 :(得分:1)
jQuery Sizzle会自动缓存从选择器创建的最近函数,以便查找DOM元素。但是元素本身不会被缓存。
此外,Sizzle维护最近编译的函数的缓存。缓存具有最大大小(可以调整但具有默认值),因此在使用大量不同选择器时不会出现内存不足错误。
答案 11 :(得分:1)
jsPerf今天失败了,但是this article表明缓存jQuery选择器的性能提升很小。
这可能仅限于浏览器缓存。测试的选择器只是一个id。应该为更复杂的选择器和不同的页面结构做更多的测试......
答案 12 :(得分:1)
$ .relectorCache()非常有用:
https://gist.github.com/jduhls/ceb7c5fdf2ae1fd2d613e1bab160e296
Gist embed:
<script src="https://gist.github.com/jduhls/ceb7c5fdf2ae1fd2d613e1bab160e296.js"></script>
答案 13 :(得分:0)
检查这是否有助https://plugins.jquery.com/cache/
作为我们常规项目的一部分来看这个