首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >jQuery/Sizzle checkContext内存泄漏

jQuery/Sizzle checkContext内存泄漏
EN

Stack Overflow用户
提问于 2013-06-24 23:23:08
回答 2查看 1.8K关注 0票数 11

在DevTools中使用“配置文件”调试我的应用程序时,我发现“分离的DOM树”正在累积。这些分离的节点具有主要由checkContext函数(来自jQuery -v1.10.1中的sizzle )组成的保留树。

我不知道该怎么做。这个结果意味着什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-03 03:36:58

这实际上是一个bug,Sizzle没有理由需要挂起上下文节点,它这么做只是因为它在设置临时变量后没有进行清理。我提交了一个issue for it,修复了它,运行了所有的Sizzle测试,并做了一个拉取请求。

如果要修补现有的jQuery或Sizzle副本,请执行以下操作:

  1. 打开jQuery或Sizzle文件
  2. 搜索matcherFromTokens函数
  3. 在其中找到以下代码(靠近顶部):

匹配器=函数( elem,context,xml ){ return ( !leadingRelative && ( xml || context !== outermostContext )) || ( (checkContext = context).nodeType?matchContext( elem,context,xml ):matchAnyContext( elem,context,xml ) );};

  • return改为var rv =,在匿名函数末尾添加checkContext = undefined;,然后添加return rv;,例如:

匹配器=函数(元素,上下文,xml ){ var ret =( !leadingRelative && ( xml ||上下文!== outermostContext )) || ( (checkContext =上下文).nodeType?matchContext( elem,context,xml ):matchAnyContext( elem,context,xml );//释放context节点(问题#299) checkContext = null;return ret;} ;

注释:该代码将null赋值给checkContext,因为这显然是他们的风格。如果是我,我会给undefined赋值。

如果在拉取请求/合并过程中提出的修复有任何问题,我将更新答案。

最好还是让Sizzle缓存选择器,因为jQuery使用编译后的带有事件委托的选择器,而你并不是真的想让它在每次发生相关事件时重新解析和重建匹配器函数,这样它才能确定元素是否与之匹配。

不幸的是,这并不是jQuery在已编译选择器中保存元素的唯一位置。它所做的每一个地方都可能是一个需要修复的bug。我只有时间追踪到另一个,我也报告并修复了(等待拉取请求落地):

如果你搜索“潜在的复杂伪代码”,你会在:not伪选择器中找到这个:

代码语言:javascript
复制
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();
            };
    }),

问题出在条件运算符中:后面的函数中:

代码语言:javascript
复制
function( elem, context, xml ) {
    input[0] = elem;
    matcher( input, null, xml, results );
    return !results.pop();
};

请注意,它永远不会清除input[0]。修复方法如下:

代码语言:javascript
复制
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();
};

这就是我目前所能找到的全部时间。

票数 4
EN

Stack Overflow用户

发布于 2013-06-24 23:33:35

Sizzle将编译的选择器存储在选择器缓存中,默认情况下最多存储50个条目。您可以尝试在进行任何选择之前设置$.expr.cacheLength = 1,并查看它们是否消失。

这是文档的https://github.com/jquery/sizzle/wiki/Sizzle-Documentation#-internal-api。看起来是内部的,所以不要在实际的生产代码中依赖它或任何东西。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17279143

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档