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/
作为我们常规项目的一部分来到这里