61

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

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

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

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

如果选择器更复杂,我可以想象这是一个不平凡的打击。

4

14 回答 14

30

始终缓存您的选择!

用同一个选择器不断地$( selector )一遍又一遍地调用是很浪费的。

或者几乎总是......您通常应该将 jQuery 对象的缓存副本保存在局部变量中,除非您希望它已经更改或者您只需要它一次。

var element = $("#someid");

element.click( function() {

  // no need to re-select #someid since we cached it
  element.hide(); 
});
于 2012-04-15T04:15:19.677 回答
16

jQuery 没有,但有可能在表达式中分配给变量,然后在后续表达式中重新使用这些变量。所以,缓存你的例子......

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

缺点是它使代码有点笨拙且难以理解。

于 2008-11-15T00:57:52.267 回答
14

这与其说是“可以吗?”,而在于“可以吗?”,不,它不能 - 自上次运行查询以来,您可能已经向 DOM 添加了额外的匹配元素。这会使缓存的结果过时,并且 jQuery 除了再次运行查询之外没有(明智的)方法可以告诉。

例如:

$('#someid .someclass').show();
$('#someid').append('<div class="someclass">New!</div>');
$('#someid .someclass').hide();

在这个例子中,如果有任何查询缓存,新添加的元素不会被隐藏——它只会隐藏之前显示的元素。

于 2008-11-16T11:26:17.427 回答
13

我刚刚做了一个解决这个问题的方法:

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 实现或任何其他使用$$符号的库。

于 2011-10-14T13:24:21.547 回答
9

我不认为它确实如此(尽管我现在不想通过阅读三千五行 JavaScript 来确定答案)。

但是,您所做的不需要多个选择器 - 这应该有效:

$("#navbar .heading:not(:empty)").hide();
于 2008-11-15T00:25:20.333 回答
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>
于 2012-07-20T17:10:49.530 回答
4

我不相信 jquery 对选择器进行任何缓存,而是依靠下面的 xpath/javascript 来处理它。话虽如此,您可以在选择器中使用许多优化。以下是一些涵盖一些基础知识的文章:

于 2008-11-15T00:23:29.887 回答
4

这 $$() 工作正常 - 在任何情况下都应该返回一个有效的 jQuery 对象,并且永远不会未定义。

小心它!它应该/不能与动态变化的选择器一起使用,例如。通过附加与选择器匹配的节点或使用伪类。

function $$(selector) {
  return cache.hasOwnProperty(selector) 
    ? cache[selector] 
    : cache[selector] = $(selector); 
};

当然,$$ 可以是任何函数名称。

于 2012-08-23T14:00:56.357 回答
2

John Resig 在 2008 年 jQuery Camp 的 Jquery Internals 演讲中确实提到了一些浏览器支持在 DOM 被修改时触发的事件。对于这种情况,可以缓存 Selctor 结果。

于 2011-03-20T10:12:54.343 回答
2

有一个很好的插件叫做jQache可以做到这一点。安装插件后,我通常会这样做:

变量 $$ = $.q;

然后就

$$("#navbar .heading").hide();

所有这一切中最好的部分是,如果您正在做动态的事情,您还可以在需要时刷新缓存,例如:

$$("#navbar .heading", true).hide(); // 刷新缓存并隐藏新的(新发现的)#navbar .heading

$$.clear(); // 完全清除缓存

于 2014-10-30T10:57:22.323 回答
2

jsPerf 今天停产了,但是这篇文章表明缓存 jQuery 选择器带来的性能提升是微乎其微的。

在此处输入图像描述

这可能只是浏览器缓存。测试的选择器只有一个 id。应该对更复杂的选择器和不同的页面结构进行更多的测试......

于 2015-07-02T09:16:22.920 回答
1

jQuery Sizzle会自动缓存最近从选择器创建的函数,以便查找 DOM 元素。但是,元素本身不会被缓存。

此外,Sizzle 维护最近编译的函数的缓存。缓存有一个最大大小(可以调整但有一个默认值),因此在使用许多不同的选择器时不会出现内存不足的错误。

于 2012-12-03T23:14:52.780 回答
1

$.selectorCache() 很有用:

https://gist.github.com/jduhls/ceb7c5fdf2ae1fd2d613e1bab160e296

要点嵌入:

<script src="https://gist.github.com/jduhls/ceb7c5fdf2ae1fd2d613e1bab160e296.js"></script>

于 2016-05-24T17:25:06.730 回答
0

检查这是否有帮助https://plugins.jquery.com/cache/

作为我们常规项目的一部分遇到这个

于 2015-05-25T05:47:47.733 回答