web-dev-qa-db-ja.com

jQueryは「セレクター」のキャッシュを実行しますか?

たとえば、最初のコードは全検索を2回実行しますか、それともDOMの変更が発生しなかった場合に結果をキャッシュするのに十分スマートでしょうか?

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

そして

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

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

セレクターがより複雑な場合、それは重要なヒットになると想像できます。

57
Allain Lalonde

jQueryはサポートしていませんが、式内の変数に割り当てて、それを後続の式で再利用する可能性があります。だから、あなたの例をキャッシュ化する...

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

欠点は、コードが少し不明瞭になり、理解しにくくなることです。

16

常に選択内容をキャッシュしてください!

同じセレクタを使用して$( selector )を繰り返し何度も呼び出すのは無駄です。

またはほとんど常に... jQueryオブジェクトのキャッシュされたコピーは、それが変更されたと予想したり、一度だけ必要になる場合を除いて、ローカル変数に保持する必要があります。

var element = $("#someid");

element.click( function() {

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

これは「するか」という問題ではありませんが、「できるか」という問題ではなく、できません。クエリを最後に実行してから、一致する要素をDOMに追加した可能性があります。これにより、キャッシュされた結果が古くなり、jQueryにはクエリを再度実行する以外に(賢明な)方法がありません。

例えば:

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

この例では、クエリのキャッシングがあった場合、新しく追加された要素は非表示にならず、以前に明らかにされた要素のみが非表示になります。

14
JoeBloggs

私はこの問題を解決する方法を実行しました:

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の実装や$$表記。

12
Aleksandr Makov

私はそうは思いません(確かに、現時点でJavaScriptの3万5千行を確認して確認する気はありません)。

しかし、あなたがしていることは複数のセレクタを必要としません-これはうまくいくはずです:

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

あなたの$$アプローチと同様に、暗記パターンを使用してグローバルをよりクリーンに保ち、$$( "。class"、 "#context"のような2番目のコンテキストパラメーターも考慮する(同じ名前の)関数を作成しました)。これは、$$が返された後に発生する連鎖関数find()を使用する場合に必要です。したがって、最初にコンテキストオブジェクトをキャッシュしない限り、単独ではキャッシュされません。また、最後にブールパラメータ(コンテキストを使用するかどうかに応じて2番目または3番目のパラメータ)を追加して、強制的に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>
6
Sefi Grossman

jqueryがセレクターのキャッシュを実行することはないと思います。その代わりに、その下にあるxpath/javascriptに依存しています。そうは言っても、セレクターで利用できる最適化はたくさんあります。ここにいくつかの基本をカバーするいくつかの記事があります:

4
Owen

この$$()は正常に機能します。どのような場合でも、決して未定義ではない有効なjQueryオブジェクトを返す必要があります。

気をつけて!動的に変化する可能性のあるセレクターを使用する必要があります。セレクターに一致するノードを追加するか、疑似クラスを使用します。

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

もちろん、$$は任意の関数名にすることができます。

3
Joschi

JQuery Camp 2008でのJquery Internals講演でのJohn Resigは、DOMが変更されたときに発生するイベントをサポートするいくつかのブラウザーについて言及しています。このような場合、Selctorの結果をキャッシュできます。

2
Anirban Deb

まさにそれを行う jQache と呼ばれる素晴らしいプラグインがあります。プラグインをインストールした後、私は通常これを行います:

var $$ = $ .q;

そして、ちょうど

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

これのすべての最もよい部分は、動的なことをしている場合、必要に応じてキャッシュをフラッシュすることもできることです。例えば:

$$( "#navbar .heading"、true).hide(); //キャッシュをフラッシュし、新しい(新しく見つけた)#navbar .headingを非表示にします

そして

$$。clear(); //キャッシュを完全にクリアします

2
justnorris

jsPerfは本日ダウンしていますが、 この記事 は、jQueryセレクターのキャッシュによるパフォーマンスの向上が最小限であることを示唆しています。

enter image description here

これは単にブラウザのキャッシュに起因する可能性があります。テストされたセレクターは、単一のIDのみでした。より複雑なセレクターと異なるページ構造については、さらにテストを行う必要があります...

2
joeytwiddle

jQuery Sizzle は、DOM要素を見つけるために、セレクターから作成された最近の関数を自動的にキャッシュします。ただし、要素自体はキャッシュされません。

さらに、Sizzleは、最近コンパイルされた関数のキャッシュを維持します。キャッシュには最大サイズ(調整可能ですがデフォルトがあります)があるため、さまざまなセレクターを多数使用してもメモリ不足エラーは発生しません。

1
Brave Dave

$ .selectorCache()は便利です:

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

要旨の埋め込み:

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

これが役立つかどうかを確認してください https://plugins.jquery.com/cache/

私たちの通常のプロジェクトの一部としてこれに遭遇しました

0
Sarath.B