Does jQuery do any kind of caching of “selectors”?

后端 未结 14 2005
挽巷
挽巷 2020-11-27 18:14

For example, will the first piece of code perform a full search twice, or is it smart enough to cache results if no DOM changes have occurred?

if ($(\"#navba         


        
相关标签:
14条回答
  • 2020-11-27 18:38

    i don't believe jquery does any caching of selectors, instead relying on xpath/javascript underneath to handle that. that being said, there are a number of optimizations you can utilize in your selectors. here are a few articles that cover some basics:

    • Optimizing jQuery selector performance
    • Performance analysis of selectors
    0 讨论(0)
  • 2020-11-27 18:40

    Similar to your $$ approach, I created a function (of the same name) that uses a memorization pattern to keep global cleaner and also accounts for a second context parameter... like $$(".class", "#context"). This is needed if you use the chained function find() that happens after $$ is returned; thus it will not be cached alone unless you cache the context object first. I also added boolean parameter to the end (2nd or 3rd parameter depending on if you use context) to force it to go back to the DOM.

    Code:

    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]; 
    }
    

    Usage:

    <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>
    
    0 讨论(0)
  • 2020-11-27 18:40

    There is a nice plugin out there called jQache that does exactly that. After installing the plugin, I usually do this:

    var $$ = $.q;

    And then just

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

    The best part of all this is that you can also flush your cache when needed if you're doing dynamic stuff, for example:

    $$("#navbar .heading", true).hide(); // flushes the cache and hides the new ( freshly found ) #navbar .heading

    And

    $$.clear(); // Clears the cache completely

    0 讨论(0)
  • 2020-11-27 18:42

    This $$() works fine - should return a valid jQuery Object in any case an never undefined.

    Be careful with it! It should/cannot with selectors that dynamically may change, eg. by appending nodes matching the selector or using pseudoclasses.

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

    And $$ could be any funciton name, of course.

    0 讨论(0)
  • 2020-11-27 18:43

    John Resig in his Jquery Internals talk at jQuery Camp 2008 does mention about some browsers supporting events which are fired when the DOM is modified. For such cases, the Selctor results could be cached.

    0 讨论(0)
  • 2020-11-27 18:44

    I just did a method for solving this problem:

    var cache = {};
    
    function $$(s)
    {
        if (cache.hasOwnProperty(s))
        {
            return $(cache[s]);
        }
    
        var e = $(s);
    
        if(e.length > 0)
        {
            return $(cache[s] = e);
        }
    
    }
    

    And it works like this:

    $$('div').each(function(){ ... });
    

    The results are accurate as far as i can tell, basing on this simple check:

    console.log($$('#forms .col.r')[0] === $('#forms .col.r')[0]);
    

    NB, it WILL break your MooTools implementation or any other library that uses $$ notation.

    0 讨论(0)
提交回复
热议问题