$.expr.cacheLength = 1
来进行实验,看看它们是否消失。这实际上是一个bug,Sizzle没有必要保留上下文节点,它之所以这样做只是因为在设置临时变量后没有进行清理。我已经为此提交了问题,并进行了修复、运行了所有的Sizzle测试,并发起了一个pull request。
如果您想修补现有的jQuery或Sizzle副本:
Open your jQuery or Sizzle file
Search for the matcherFromTokens
function
Find this code within it (near the top):
matchers = [ function( elem, context, xml ) {
return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
(checkContext = context).nodeType ?
matchContext( elem, context, xml ) :
matchAnyContext( elem, context, xml ) );
} ];
Change the return
to var rv =
, and add checkContext = undefined;
and then return rv;
at the end of the anonymous function, e.g.:
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
。
如果在合并过程中对修复程序提出任何问题,我将更新答案。
最好继续让Sizzle缓存选择器,因为jQuery使用编译的选择器与事件委托一起使用,并且不希望每次相关事件发生时都需要重新解析和重建匹配函数以确定元素是否与其匹配。
不幸的是,这不是jQuery保留元素的编译选择器的唯一位置。它所做的每个地方可能是一个可以修复的错误。我只有时间追踪到另一个地方,我也已经报告并修复了它(等待合并请求被接受):
如果搜索"Potentially complex pseudos",您会在: 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();
};
目前我只有时间追踪到这些。
checkContext
只是一个临时变量,用于在上面的匿名函数调用 matchContext
和 matchAnyContext
时给它们提供访问权限(我猜由于某种原因无法将其传递给它们)。匹配完成后没有必要继续持有上下文元素(而且完全不需要)。我真的很惊讶修复如此容易,虽然我认为我们必须等待并在以后清除它。但所有测试都通过了,所以我们将看看它是否经得起审查... - T.J. Crowder