jQuery是否会对“select器”进行任何caching?

例如,第一段代码是否会执行两次完整的search,或者如果没有发生DOM更改,是否足够聪明来caching结果?

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

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

如果select器更复杂,我可以想象它是一个不平凡的命中。

jQuery不会,但有可能在expression式中分配variables,然后在后续expression式中重新使用这些variables。 所以,caching – 如果你的例子…

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

不利的一面是它使代码变得更加笨拙,难以理解。

始终caching您的select!

不断地用相同的select器反复调用$( selector )是浪费的。

或者几乎总是…你通常应该把一个jQuery对象的caching副本保存在一个局部variables中,除非你期望它已经改变或者你只需​​要一次。

 var element = $("#someid"); element.click( function() { // no need to re-select #someid since we cached it element.hide(); }); 

这不是一个“这样做”的问题,而是“可以吗?”,而不是,它不能 – 自查询上次运行以来,您可能为DOM添加了其他匹配元素。 这将使caching的结果陈旧,jQuery将没有(明智的)方式告诉除了再次运行查询以外。

例如:

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

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

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

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

我不认为这样做(尽pipe我不想通过阅读三千五百行JavaScript来确定)。

然而,你在做什么不需要多个select器 – 这应该工作:

 $("#navbar .heading:not(:empty)").hide(); 

类似于你的$$方法,我创build了一个使用记忆模式的函数(同名),以保持全局更清洁,同时也考虑了第二个上下文参数,比如$$(“.class”,“#context” )。 如果使用在返回$$之后发生的链式函数find(),则这是必需的; 因此除非先caching上下文对象,否则不会单独caching。 我还添加了布尔参数到最后(取决于你是否使用上下文第二或第三个参数)强制它返回到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>  <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> 

我不相信jquery做任何caching的select器,而是依靠xpath / JavaScript下面来处理。 这是说,有一些优化,你可以在你的select使用。 这里有几篇文章涵盖了一些基础知识:

  • 优化jQueryselect器的性能
  • select器的性能分析

这$$()工作正常 – 应该返回一个有效的jQuery对象,在任何情况下,永远不会undefined。

小心点! 它应该/不能dynamic地改变select器,例如。 通过追加匹配select器的节点或使用伪类。

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

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

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

那里有一个很好的插件叫做jQache ,就是这样做的。 安装插件后,我通常这样做:

var $$ = $ .q;

然后就是

$$(“#navbar .heading”)。hide();

所有这一切的最好的部分是,如果你正在做dynamic的东西,你也可以在需要时刷新caching,例如:

$$(“#navbar .heading”,true).hide(); //刷新caching并隐藏新的(新发现的)#navbar .heading

。$$清晰(); //完全清除caching

jQuery Sizzle会自动caching从select器创build的最近的函数,以查找DOM元素。 但是这些元素本身没有被caching。

另外,Sizzle维护最近编译的函数的caching。 caching有一个最大的大小(可以调整,但有一个默认值),所以当使用很多不同的select器时,不会出现内存不足的错误。

jsPerf今天停止运行,但是这篇文章暗示,cachingjQueryselect器的性能提升将是最小的。

在这里输入图像描述

这可能只是简单的浏览器caching。 testingselect器只是一个单一的ID。 应该为更复杂的select器和不同的页面结构做更多的testing。

$ .selectorCache()是有用的:

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

要点embedded:

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

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

作为我们常规项目的一部分来到这里