11

DevTools で「プロファイル」を使用してアプリをデバッグしているときに、「分離された DOM ツリー」が蓄積していることがわかりました。これらの切り離されたノードには、主に関数で構成される保持ツリーがあります ( jQuery内のシズルcheckContextから来ています- v1.10.1)。

ヒープのスナップショット

これをどのように進めればよいかわかりません。この結果は何を意味するのでしょうか?

4

2 に答える 2

6

Sizzle は、コンパイルされたセレクターをセレクター キャッシュに保存します。デフォルトでは、最大 50 のエントリが保存されます。選択を行う前に設定を試して$.expr.cacheLength = 1みて、それらがなくなるかどうかを確認してください。

これがドキュメントhttps://github.com/jquery/sizzle/wiki/Sizzle-Documentation#-internal-apiです。内部のように見えるので、実際の製品コードに依存しないでください。

于 2013-06-24T15:33:35.077 に答える
4

これは実際にはバグです。Sizzle がコンテキスト ノードにハングアップする必要がある理由はありません。一時変数を設定した後、クリーンアップされていないため、Sizzle がハングアップしているだけです。問題を提出し、修正し、すべてのシズル テストを実行し、プル リクエストを行いました。

jQuery または Sizzle の既存のコピーにパッチを適用する場合:

  1. jQuery または Sizzle ファイルを開きます

  2. matcherFromTokens関数を検索する

  3. その中で次のコードを見つけます (上部近く):

    matchers = [ function( elem, context, xml ) {
        return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
            (checkContext = context).nodeType ?
                matchContext( elem, context, xml ) :
                matchAnyContext( elem, context, xml ) );
    } ];
    
  4. を に変更しreturn、無名関数の最後にandvar rv =を追加します。例:checkContext = undefined;return rv;

    matchers = [ function( elem, context, xml ) {
        var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
            (checkContext = context).nodeType ?
                matchContext( elem, context, xml ) :
                matchAnyContext( elem, context, xml ) );
        // Release the context node (issue #299)
        checkContext = null;
        return ret;
    } ];
    

:明らかにそれが彼らのスタイルであるため、そのコードはに割り当てnullられます。checkContext私だったら、undefined代わりに割り当てます。

プル リクエスト / マージ プロセス中に発生した修正に問題がある場合は、回答を更新します。

jQueryはコンパイルされたセレクターをイベント委譲で使用し、関連するイベントが発生するたびにマッチャー関数を再解析して再構築する必要がないため、セレクターをSizzleキャッシュのままにしておくことをお勧めします。それに合わせます。


残念ながら、jQuery がコンパイル済みセレクターの要素を保持する場所はこれだけではありません。それが行う各場所は、おそらく修正を使用できるバグです。私は他の1つを追跡する時間しかありませんでした。これも報告して修正しました(プルリクエストが上陸するのを待っています):

「潜在的に複雑な疑似」を検索すると、:not疑似セレクターの次のものが見つかります。

pseudos: {
    // Potentially complex pseudos
    "not": markFunction(function( selector ) {
        // Trim the selector passed to compile
        // to avoid treating leading and trailing
        // spaces as combinators
        var input = [],
            results = [],
            matcher = compile( selector.replace( rtrim, "$1" ) );

        return matcher[ expando ] ?
            markFunction(function( seed, matches, context, xml ) {
                var elem,
                    unmatched = matcher( seed, null, xml, [] ),
                    i = seed.length;

                // Match elements unmatched by `matcher`
                while ( i-- ) {
                    if ( (elem = unmatched[i]) ) {
                        seed[i] = !(matches[i] = elem);
                    }
                }
            }) :
            function( elem, context, xml ) {
                input[0] = elem;
                matcher( input, null, xml, results );
                return !results.pop();
            };
    }),

:問題は、条件演算子の後の関数にあります。

function( elem, context, xml ) {
    input[0] = elem;
    matcher( input, null, xml, results );
    return !results.pop();
};

クリアされないことに注意してくださいinput[0]。修正は次のとおりです。

function( elem, context, xml ) {
    input[0] = elem;
    matcher( input, null, xml, results );
    // Don't keep the element (issue #299)
    input[0] = null;
    return !results.pop();
};

現時点で追跡する時間があるのはそれだけです。

于 2014-12-02T19:36:58.200 に答える