jQuery是否会对“选择器”进行任何缓存?

时间:2008-11-15 00:13:54

标签: jquery jquery-selectors

例如,第一段代码是否会执行两次完整搜索,或者如果没有发生DOM更改,它是否足够智能以缓存结果?

if ($("#navbar .heading").text() > "") {
  $("#navbar .heading").hide();
}

var $heading = $("#navbar .heading");

if ($heading.text() > "") {
  $heading.hide();
}

如果选择器更复杂,我可以想象这是一个非常重要的命中。

14 个答案:

答案 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选择器的性能提升很小。

enter image description here

这可能仅限于浏览器缓存。测试的选择器只是一个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/

作为我们常规项目的一部分来看这个