code

jQuery는 "선택자"의 캐싱을 수행합니까?

codestyles 2020. 12. 24. 23:46
반응형

jQuery는 "선택자"의 캐싱을 수행합니까?


예를 들어, 첫 번째 코드가 전체 검색을 두 번 수행합니까, 아니면 DOM 변경이 발생하지 않은 경우 결과를 캐시 할만큼 똑똑합니까?

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

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

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

선택기가 더 복잡하다면 사소한 히트라고 생각할 수 있습니다.


jQuery는 그렇지 않지만 표현식 내에서 변수에 할당 한 다음 후속 표현식에서 다시 사용할 가능성이 있습니다. 그래서, 당신의 예를 캐시 화 ...

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

단점은 코드가 약간 흐릿하고 그루 킹이 어렵다는 것입니다.


항상 선택 사항을 캐시하십시오!

$( selector )동일한 선택기 로 계속해서 계속 호출 하는 것은 낭비 입니다.

또는 거의 항상 ... 일반적으로 jQuery 객체의 캐시 된 복사본을 로컬 변수에 보관해야합니다. 단 한 번만 필요하거나 변경 될 것으로 예상하지 않는 한.

var element = $("#someid");

element.click( function() {

  // no need to re-select #someid since we cached it
  element.hide(); 
});

그것은 '할 수 있습니까?'의 문제가 아니라 '할 수 있습니까?', 아니요, 할 수 없습니다. 쿼리가 마지막으로 실행 된 이후에 추가 일치 요소를 DOM에 추가했을 수 있습니다. 이것은 캐시 된 결과를 부실하게 만들고 jQuery는 쿼리를 다시 실행하는 것 외에 다른 것을 알릴 수있는 (현명한) 방법이 없습니다.

예를 들면 :

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

이 예에서 새로 추가 된 요소는 쿼리의 캐싱이있는 경우 숨겨지지 않고 이전에 공개 된 요소 만 숨겨집니다.


이 문제를 해결하는 방법을 방금 수행했습니다.

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

NB, 그것은 MooTools 구현 또는 $$표기법 을 사용하는 다른 라이브러리를 손상시킬 것 입니다.


나는 그렇게 생각하지 않는다 (확실히 알아보기 위해 현재 3 천 5 천 줄의 자바 스크립트를 읽고 싶지는 않지만).

그러나 수행중인 작업에는 여러 선택기가 필요하지 않습니다.

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

$$ 접근 방식과 유사하게, 저는 암기 패턴을 사용하여 전역을 깨끗하게 유지하고 두 번째 컨텍스트 매개 변수를 설명하는 함수 (같은 이름의)를 만들었습니다. 예를 들면 $$ ( ". 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>

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:


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.


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.


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


jsPerf is down today, but this article suggests that the performance gains from caching jQuery selectors would be minimal.

enter image description here

This may simply be down to browser caching. The selector tested was only a single id. More tests should be done for more complicated selectors and different page structures...


jQuery Sizzle does automatically cache the recent functions that have been created from the selectors in order to find DOM elements. However the elements themselves are not cached.

Additionally, Sizzle maintains a cache of the most recently compiled functions. The cache has a maximum size (which can be adjusted but has a default) so you don’t get out-of-memory errors when using a lot of different selectors.


$.selectorCache() is useful:

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

Gist embed:

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


Check if this helps https://plugins.jquery.com/cache/

Came across this as part of our regular project

ReferenceURL : https://stackoverflow.com/questions/291841/does-jquery-do-any-kind-of-caching-of-selectors

반응형